httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ruediger Pluem <>
Subject Re: mod_proxy race condition bug #37770
Date Mon, 19 May 2008 20:09:34 GMT

On 05/19/2008 09:36 PM, Adam Woodworth wrote:
> So let's consider the case of a web browser that uses keepalives.  If
> the web browser has a keepalive connection, and the connection closes
> behind it's back so that the next time the browser tries to use the
> connection it fails (like this problem we're having with mod_proxy),
> what should the web browser do?

It makes a new connection to the server and sends the request again. Of
course it should only do this if the request was idempotent. Practice shows
that most browsers don't care and also resent non idempotent requests, but
this is a browser issue.

> I bring this up because while I certainly never see Firefox regularly
> fail to load pages, I'm seeing mod_proxy fail with some regularity,
> perhaps only a fraction of a percent, but still...  And you would
> think you'd see the same problem with any sort of browser/proxy.
> Has anyone seen the socket code for Firefox to see if they're doing
> something more clever to prevent dead connections from being used?

You don't need the firefox code to see this. Just use a network sniffer and
create a dummy server like the following ugly hack:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
     int listen_fd;
     int fd;
     struct sockaddr_storage addr;
     socklen_t addrlen = sizeof(addr);
     struct sockaddr_in addr_in;
     struct linger l = {1, 0};
     int val = 1;
     char buffer[1024];
     char response[] = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";

     listen_fd = socket(PF_INET, SOCK_STREAM, 0);
     memset(&addr_in, 0, sizeof(struct sockaddr_in));
     addr_in.sin_family = AF_INET;
     addr_in.sin_port = ntohs(8080);
     setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
     bind(listen_fd, &addr_in, sizeof(addr_in));
     listen(listen_fd, 50);
     fd = accept(listen_fd, &addr, &addrlen);
     read(fd, buffer, sizeof(buffer));
     write(fd, (void *)response, strlen(response));
     printf("%s\n", response);
     read(fd, buffer, sizeof(buffer));
     setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof l);
     close(fd); /* sends TCP RST rather than FIN */
     return 0;

It just closes down the connection with a RST on the second request on the
same connection. You will notice in the network sniffer that the browser opens
a new TCP connection and resends the request.



View raw message