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)
struct linger lin;
struct timeval tv;
socklen_t l;
int i;
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);
if (memcmp(&lin, &linger, l))
need_linger = 1;
#ifdef SO_SNDTIMEO_WORKS
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);
if (memcmp(&tv, &tv_sndtimeo, l))
need_sndtimeo = 1;
......@@ -126,7 +135,11 @@ sock_test(int fd)
#ifdef SO_RCVTIMEO_WORKS
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);
if (memcmp(&tv, &tv_rcvtimeo, l))
need_rcvtimeo = 1;
......@@ -168,16 +181,16 @@ VCA_Prep(struct sess *sp)
if (need_test)
sock_test(sp->fd);
if (need_linger)
AZ(setsockopt(sp->fd, SOL_SOCKET, SO_LINGER,
TCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_LINGER,
&linger, sizeof linger));
#ifdef SO_SNDTIMEO_WORKS
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));
#endif
#ifdef SO_RCVTIMEO_WORKS
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));
#endif
}
......@@ -365,8 +378,9 @@ vca_return_session(struct sess *sp)
* Set nonblocking in the worker-thread, before passing to the
* acceptor thread, to reduce syscall density of the latter.
*/
TCP_nonblocking(sp->fd);
if (vca_act->pass == NULL)
if (TCP_nonblocking(sp->fd))
vca_close_session(sp, "remote closed");
else if (vca_act->pass == NULL)
assert(sizeof sp == write(vca_pipes[1], &sp, sizeof sp));
else
vca_act->pass(sp);
......
......@@ -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_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_hisname(int sock, char *abuf, unsigned alen, char *pbuf, unsigned plen);
int TCP_filter_http(int sock);
void TCP_blocking(int sock);
void TCP_nonblocking(int sock);
void TCP_linger(int sock, int linger);
int TCP_blocking(int sock);
int TCP_nonblocking(int sock);
int TCP_linger(int sock, int linger);
#ifdef SOL_SOCKET
void TCP_name(const struct sockaddr *addr, unsigned l, char *abuf,
unsigned alen, char *pbuf, unsigned plen);
......
......@@ -154,22 +154,26 @@ TCP_filter_http(int sock)
* at least on FreeBSD.
*/
void
int
TCP_blocking(int sock)
{
int i;
int i, j;
i = 0;
AZ(ioctl(sock, FIONBIO, &i));
j = ioctl(sock, FIONBIO, &i);
TCP_Assert(j);
return (j);
}
void
int
TCP_nonblocking(int sock)
{
int i;
int i, j;
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)
* Set or reset SO_LINGER flag
*/
void
int
TCP_linger(int sock, int linger)
{
struct linger lin;
......@@ -264,5 +268,6 @@ TCP_linger(int sock, int linger)
memset(&lin, 0, sizeof lin);
lin.l_onoff = linger;
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