diff --git a/man/3proxy.cfg.5 b/man/3proxy.cfg.5 index dee85e2..5e49164 100644 --- a/man/3proxy.cfg.5 +++ b/man/3proxy.cfg.5 @@ -526,9 +526,11 @@ can use %A as produced archive name and %F as filename. \fBCHAIN\fR timeout for reading data from chained connection .br \fBLINGER\fR timeout to deliver buffered data after one of the sides has closed -its sending side, also used as SO_LINGER value on outgoing connections. Too small -value may cause the tail of the data to be lost on slow connections, too large one -delays release of the sockets. +its sending side, and for httpsrv to read what is left of a request before it +closes the connection. Too small value may cause the tail of the data to be +lost on slow connections, too large one delays release of the sockets. +Sockets are closed without SO_LINGER: the system sends what is queued after +the close, the connection's thread and slot freed at once. .br default timeouts 1 5 30 60 180 1800 15 60 15 5 5 .br diff --git a/src/common.c b/src/common.c index a1f2fd0..666af55 100644 --- a/src/common.c +++ b/src/common.c @@ -789,9 +789,6 @@ int doconnect(struct clientparam * param){ if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsr, &size)==-1) {return (14);} } else { -#ifndef _WIN32 - struct linger lg = {1,param->srv->timeouts[LINGER_TO]}; -#endif int tries = RANGETRIES; if(SAISNULL(¶m->sinsr)){ @@ -823,10 +820,6 @@ int doconnect(struct clientparam * param){ *SAPORT(¶m->sinsl) = 0; setopts(param->remsock, ¶m->srv->srvsockopts, param->srv->maxseg); -#ifndef _WIN32 - /* not on Windows, see the accepting side in proxymain.c */ - param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); -#endif if(extbindtodevice(param, param->remsock)) return 12; #ifdef WITH_UN if(*SAFAMILY(¶m->sinsl) != AF_UNIX) diff --git a/src/ftppr.c b/src/ftppr.c index 181ae76..faaa2d3 100644 --- a/src/ftppr.c +++ b/src/ftppr.c @@ -23,18 +23,11 @@ void * ftpprchild(struct clientparam* param) { SOCKET sc = INVALID_SOCKET, ss = INVALID_SOCKET, clidatasock = INVALID_SOCKET; SASIZETYPE sasize; char * req = NULL; -#ifndef _WIN32 - struct linger lg; -#endif struct pollfd fds; buf = param->tmpbuf; /* a filter may replace it with one of its own */ param->ctrlsock = param->clisock; param->operation = CONNECT; -#ifndef _WIN32 - lg.l_onoff = 1; - lg.l_linger = param->srv->timeouts[STRING_L]; -#endif if(socksend(param, param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, param->srv->timeouts[STRING_S])!=11) {RETURN (801);} for(;;){ i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 10, '\n', param->srv->timeouts[CONNECTION_S]); @@ -269,11 +262,6 @@ void * ftpprchild(struct clientparam* param) { } sc = param->remsock; param->remsock = ss; -#ifndef _WIN32 - /* not on Windows, see the accepting side in proxymain.c */ - param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); - param->srv->so._setsockopt(param->sostate, clidatasock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); -#endif param->clisock = clidatasock; res = mapsocket(param, param->srv->timeouts[CONNECTION_S]); if(param->remsock != INVALID_SOCKET) { diff --git a/src/mainclient.c b/src/mainclient.c index d029d80..47ea0f5 100644 --- a/src/mainclient.c +++ b/src/mainclient.c @@ -447,8 +447,7 @@ void releaseparam(struct clientparam * param) { /* the sockets were closed and the filters cleared with it */ param->sostate = NULL; /* Leaving the service comes last. Once its last child is gone, srvfree() - frees the service along with its socket functions, filters and mutex, - and a close above may have lingered for seconds before getting here. */ + frees the service along with its socket functions, filters and mutex. */ if(param->srv){ _3proxy_mutex_lock(¶m->srv->counter_mutex); if(param->prev || param->next || param->srv->child == param){ diff --git a/src/maintcp.c b/src/maintcp.c index cd9d839..d9925e5 100644 --- a/src/maintcp.c +++ b/src/maintcp.c @@ -55,9 +55,7 @@ static int tcpnext(struct srvstart *s, SOCKET *client, int *nlog){ SASIZETYPE size; unsigned char buf[256]; int error = 0, opt = 1, res, waited; -#ifndef _WIN32 - struct linger lg; -#else +#ifdef _WIN32 unsigned long ul = 1; #endif @@ -166,14 +164,10 @@ static int tcpnext(struct srvstart *s, SOCKET *client, int *nlog){ #else fcntl(new_sock,F_SETFL,O_NONBLOCK | fcntl(new_sock,F_GETFL)); #endif -#ifndef _WIN32 - /* Not on Windows: there closesocket() on a non-blocking socket with a linger - timeout fails with WSAEWOULDBLOCK while data is queued, leaving the socket - open. Without it the close completes in the background, data first. */ - lg.l_onoff = 1; - lg.l_linger = srv->timeouts[STRING_L]; - srv->so._setsockopt(srv->so.state, new_sock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); -#endif +/* No linger: a close completes in the background, what is queued sent + first; waiting for the peer to acknowledge it would only hold the thread + (or the event loop) and the slot, and its time running out would reset + the connection, losing what was still queued. */ srv->so._setsockopt(srv->so.state, new_sock, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int)); *client = new_sock; return NEXT_CLIENT; diff --git a/src/proxymain.c b/src/proxymain.c index 30f90c8..4cdeb83 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -215,7 +215,6 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int int res; #ifndef _WIN32 int opt = 1; - struct linger lg; struct clientparam *newparam; #endif @@ -255,9 +254,6 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int if(s.inetd) { fcntl(0,F_SETFL,O_NONBLOCK | fcntl(0,F_GETFL)); if(!s.isudp){ - lg.l_onoff = 1; - lg.l_linger = s.srv.timeouts[STRING_L]; - s.srv.so._setsockopt(s.srv.so.state, 0, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); s.srv.so._setsockopt(s.srv.so.state, 0, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int)); } s.defparam.clisock = 0;