r2641 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Fri May 30 23:39:57 CEST 2008


Author: phk
Date: 2008-05-30 23:39:56 +0200 (Fri, 30 May 2008)
New Revision: 2641

Modified:
   trunk/varnish-cache/bin/varnishd/common.h
   trunk/varnish-cache/bin/varnishd/tcp.c
Log:
Back in the mists of time, the SocketWizards were so happy to get
any connections at all, that they didn't even consider that maybe
connect(2) should have a timeout argument.

Add TCP_connect() which addresses this shortcoming, using what I
belive is a widely supported workaround.

Not to POSIX: please fix.



Modified: trunk/varnish-cache/bin/varnishd/common.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/common.h	2008-05-27 07:10:22 UTC (rev 2640)
+++ trunk/varnish-cache/bin/varnishd/common.h	2008-05-30 21:39:56 UTC (rev 2641)
@@ -46,5 +46,8 @@
 int TCP_filter_http(int sock);
 void TCP_blocking(int sock);
 void TCP_nonblocking(int sock);
+#ifdef SOL_SOCKET
+int TCP_connect(int s, const struct sockaddr *name, socklen_t namelen, int msec);
+#endif
 
 #define TRUST_ME(ptr)	((void*)(uintptr_t)(ptr))

Modified: trunk/varnish-cache/bin/varnishd/tcp.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/tcp.c	2008-05-27 07:10:22 UTC (rev 2640)
+++ trunk/varnish-cache/bin/varnishd/tcp.c	2008-05-30 21:39:56 UTC (rev 2641)
@@ -39,6 +39,7 @@
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <netdb.h>
+#include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -138,3 +139,55 @@
 	i = 1;
 	AZ(ioctl(sock, FIONBIO, &i));
 }
+
+/*--------------------------------------------------------------------
+ * On TCP a connect(2) can block for a looong time, and we don't want that.
+ * Unfortunately, the SocketWizards back in those days were happy to wait
+ * any amount of time for a connection, so the connect(2) syscall does not
+ * take an argument for patience.
+ *
+ * There is a little used work-around, and we employ it at our peril.
+ *
+ */
+
+int
+TCP_connect(int s, const struct sockaddr *name, socklen_t namelen, int msec)
+{
+	int i, k;
+	socklen_t l;
+	struct pollfd fds[1];
+
+	assert(s >= 0);
+
+	/* Set the socket non-blocking */
+	TCP_nonblocking(s);
+
+	/* Attempt the connect */
+	i = connect(s, name, namelen);
+	if (i == 0 || errno != EINPROGRESS)
+		return (i);
+
+	/* Exercise our patience, polling for write */
+	fds[0].fd = s;
+	fds[0].events = POLLWRNORM;
+	fds[0].revents = 0;
+	i = poll(fds, 1, msec);
+
+	if (i == 0) {
+		/* Timeout, close and give up */
+		errno = ETIMEDOUT;
+		return (-1);
+	}
+
+	/* Find out if we got a connection */
+	l = sizeof k;
+	AZ(getsockopt(s, SOL_SOCKET, SO_ERROR, &k, &l));
+
+	/* An error means no connection established */
+	errno = k;
+	if (k)
+		return (-1);
+
+	TCP_blocking(s);
+	return (0);
+}




More information about the varnish-commit mailing list