Mailing List Archive

r2641 - trunk/varnish-cache/bin/varnishd
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);
+}