[Zope-dev] Zope closes connection if the client closes the write-end of connection
Izak Burger
izak at upfrontsystems.co.za
Thu Oct 15 06:41:51 EDT 2009
Hi all,
Yesterday we tried to get the backend probe feature of varnish to work
with zope. It failed, claiming that a response was not received.
Checking the Z2 log showed that the request was received but that zero
bytes was transferred. Using tcpdump shows that varnish closes the
connection before zope can send the response.
I eventually distilled the check varnish uses into a small C program,
and an interesting problem shows up. When you call shutdown(fd, SHUT_WR)
on your socket connection, in effect telling zope that you're done
talking to it, it looks like zope responds in kind by not talking to you
either. I deduce this from the fact that poll() returns POLLHUP in
revents and read() returns zero (EOF). POLLHUP, if I understand this
correctly, means the other side (zope) has hung up.
This effectively makes it impossible to use certain kinds of monitoring
software with zope, specifically varnish.
I would appreciate it if someone in the know could look at the code,
tell me what I (and by extension varnish) am doing wrong, or whether
this is perhaps a bug in zope (which I strongly suspect).
The attached C code works fine against apache, and it also works fine
against zope if you remove the shutdown() call.
regards,
Izak
--- snip: poll.c ---
#define URL "/"
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv){
struct pollfd fds[1];
int timeout_msecs = 5000;
int ret;
int i, sd, request_size, offset;
struct sockaddr_in addr;
char buf[1024];
if(argc < 3){
fprintf(stderr, "Usage: %s ip port\n", argv[0]);
return 1;
}
/* Open network connection */
sd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = htons(atoi(argv[2]));
if (connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0){
perror("connect");
return 1;
}
/* Send the request */
request_size = snprintf(buf, sizeof(buf),
"GET %s HTTP/1.0\r\nConnection: close\r\n\r\n", URL);
offset = 0;
while(offset < request_size){
i = write(sd, buf+offset, request_size-offset);
offset += i;
}
/* Shutdown the write side */
shutdown(sd, SHUT_WR);
/* Now wait for data to come back */
do {
fds[0].fd = sd;
fds[0].events = POLLIN;
fds[0].revents = 0;
ret = poll(fds, 1, timeout_msecs);
if (ret > 0) {
printf("%d POLLIN events on fd %d\n", ret, fds[0].fd);
printf("revents = %d\n", fds[0].revents);
i = read(sd, buf, sizeof(buf));
printf("Read %d bytes from %d\n", i, sd);
} else if (ret == 0){
printf("Timeout\n");
} else {
perror("poll");
}
} while(i>0);
}
--- snip ---
More information about the Zope-Dev
mailing list