Commit 5f7d80c5 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Try to handle socket state calls that return errno's relating

to the client absconding the TCP connection.

This comes to the fore on Solaris, where not only systemcalls which
push data through sockets (read,write,select...) return these errors,
but also socket-state calls (setsockopt, ioctl, fcntl) do.

Root cause of trouble in #626 & al.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4572 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d398d9ab
...@@ -105,16 +105,25 @@ sock_test(int fd) ...@@ -105,16 +105,25 @@ sock_test(int fd)
struct linger lin; struct linger lin;
struct timeval tv; struct timeval tv;
socklen_t l; socklen_t l;
int i;
l = sizeof lin; l = sizeof lin;
AZ(getsockopt(fd, SOL_SOCKET, SO_LINGER, &lin, &l)); i = getsockopt(fd, SOL_SOCKET, SO_LINGER, &lin, &l);
if (i) {
TCP_Assert(i);
return;
}
assert(l == sizeof lin); assert(l == sizeof lin);
if (memcmp(&lin, &linger, l)) if (memcmp(&lin, &linger, l))
need_linger = 1; need_linger = 1;
#ifdef SO_SNDTIMEO_WORKS #ifdef SO_SNDTIMEO_WORKS
l = sizeof tv; l = sizeof tv;
AZ(getsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &l)); i = getsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &l);
if (i) {
TCP_Assert(i);
return;
}
assert(l == sizeof tv); assert(l == sizeof tv);
if (memcmp(&tv, &tv_sndtimeo, l)) if (memcmp(&tv, &tv_sndtimeo, l))
need_sndtimeo = 1; need_sndtimeo = 1;
...@@ -126,7 +135,11 @@ sock_test(int fd) ...@@ -126,7 +135,11 @@ sock_test(int fd)
#ifdef SO_RCVTIMEO_WORKS #ifdef SO_RCVTIMEO_WORKS
l = sizeof tv; l = sizeof tv;
AZ(getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &l)); i = getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &l);
if (i) {
TCP_Assert(i);
return;
}
assert(l == sizeof tv); assert(l == sizeof tv);
if (memcmp(&tv, &tv_rcvtimeo, l)) if (memcmp(&tv, &tv_rcvtimeo, l))
need_rcvtimeo = 1; need_rcvtimeo = 1;
...@@ -168,16 +181,16 @@ VCA_Prep(struct sess *sp) ...@@ -168,16 +181,16 @@ VCA_Prep(struct sess *sp)
if (need_test) if (need_test)
sock_test(sp->fd); sock_test(sp->fd);
if (need_linger) if (need_linger)
AZ(setsockopt(sp->fd, SOL_SOCKET, SO_LINGER, TCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_LINGER,
&linger, sizeof linger)); &linger, sizeof linger));
#ifdef SO_SNDTIMEO_WORKS #ifdef SO_SNDTIMEO_WORKS
if (need_sndtimeo) if (need_sndtimeo)
AZ(setsockopt(sp->fd, SOL_SOCKET, SO_SNDTIMEO, TCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_SNDTIMEO,
&tv_sndtimeo, sizeof tv_sndtimeo)); &tv_sndtimeo, sizeof tv_sndtimeo));
#endif #endif
#ifdef SO_RCVTIMEO_WORKS #ifdef SO_RCVTIMEO_WORKS
if (need_rcvtimeo) if (need_rcvtimeo)
AZ(setsockopt(sp->fd, SOL_SOCKET, SO_RCVTIMEO, TCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_RCVTIMEO,
&tv_rcvtimeo, sizeof tv_rcvtimeo)); &tv_rcvtimeo, sizeof tv_rcvtimeo));
#endif #endif
} }
...@@ -365,8 +378,9 @@ vca_return_session(struct sess *sp) ...@@ -365,8 +378,9 @@ vca_return_session(struct sess *sp)
* Set nonblocking in the worker-thread, before passing to the * Set nonblocking in the worker-thread, before passing to the
* acceptor thread, to reduce syscall density of the latter. * acceptor thread, to reduce syscall density of the latter.
*/ */
TCP_nonblocking(sp->fd); if (TCP_nonblocking(sp->fd))
if (vca_act->pass == NULL) vca_close_session(sp, "remote closed");
else if (vca_act->pass == NULL)
assert(sizeof sp == write(vca_pipes[1], &sp, sizeof sp)); assert(sizeof sp == write(vca_pipes[1], &sp, sizeof sp));
else else
vca_act->pass(sp); vca_act->pass(sp);
......
...@@ -60,12 +60,16 @@ int SUB_run(struct vsb *sb, sub_func_f *func, void *priv, const char *name, ...@@ -60,12 +60,16 @@ int SUB_run(struct vsb *sb, sub_func_f *func, void *priv, const char *name,
#define TCP_ADDRBUFSIZE 64 #define TCP_ADDRBUFSIZE 64
#define TCP_PORTBUFSIZE 16 #define TCP_PORTBUFSIZE 16
#define TCP_Check(a) ((a) == 0 || errno == ECONNRESET || errno == ENOTCONN)
#define TCP_Assert(a) assert(TCP_Check(a))
void TCP_myname(int sock, char *abuf, unsigned alen, char *pbuf, unsigned plen); void TCP_myname(int sock, char *abuf, unsigned alen, char *pbuf, unsigned plen);
void TCP_hisname(int sock, char *abuf, unsigned alen, char *pbuf, unsigned plen); void TCP_hisname(int sock, char *abuf, unsigned alen, char *pbuf, unsigned plen);
int TCP_filter_http(int sock); int TCP_filter_http(int sock);
void TCP_blocking(int sock); int TCP_blocking(int sock);
void TCP_nonblocking(int sock); int TCP_nonblocking(int sock);
void TCP_linger(int sock, int linger); int TCP_linger(int sock, int linger);
#ifdef SOL_SOCKET #ifdef SOL_SOCKET
void TCP_name(const struct sockaddr *addr, unsigned l, char *abuf, void TCP_name(const struct sockaddr *addr, unsigned l, char *abuf,
unsigned alen, char *pbuf, unsigned plen); unsigned alen, char *pbuf, unsigned plen);
......
...@@ -154,22 +154,26 @@ TCP_filter_http(int sock) ...@@ -154,22 +154,26 @@ TCP_filter_http(int sock)
* at least on FreeBSD. * at least on FreeBSD.
*/ */
void int
TCP_blocking(int sock) TCP_blocking(int sock)
{ {
int i; int i, j;
i = 0; i = 0;
AZ(ioctl(sock, FIONBIO, &i)); j = ioctl(sock, FIONBIO, &i);
TCP_Assert(j);
return (j);
} }
void int
TCP_nonblocking(int sock) TCP_nonblocking(int sock)
{ {
int i; int i, j;
i = 1; i = 1;
AZ(ioctl(sock, FIONBIO, &i)); j = ioctl(sock, FIONBIO, &i);
TCP_Assert(j);
return (j);
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -255,7 +259,7 @@ TCP_set_read_timeout(int s, double seconds) ...@@ -255,7 +259,7 @@ TCP_set_read_timeout(int s, double seconds)
* Set or reset SO_LINGER flag * Set or reset SO_LINGER flag
*/ */
void int
TCP_linger(int sock, int linger) TCP_linger(int sock, int linger)
{ {
struct linger lin; struct linger lin;
...@@ -264,5 +268,6 @@ TCP_linger(int sock, int linger) ...@@ -264,5 +268,6 @@ TCP_linger(int sock, int linger)
memset(&lin, 0, sizeof lin); memset(&lin, 0, sizeof lin);
lin.l_onoff = linger; lin.l_onoff = linger;
i = setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof lin); i = setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof lin);
assert(i == 0 || errno == EBADF); TCP_Assert(i);
return (i);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment