Hi all,

The attached patch makes mod_proxy thread safe, and at the same time
fixes some nasty behavior caused by the non-thread-safeness of the
existing mod_proxy code.

Like last time, the proxy needs to attach the downstream conn_rec to the
upstream conn_rec so that keepalives can be supported. In the mean time
though, it has become clear that this link is necessary for mod_proxy to
work.

It's been suggested that the permanent solution is to allow a mechanism
where modules can save per-connection data other than strings (c->notes)
alongside the conn_rec, but in the meantime we need a temporary solution
so that mod_proxy can work.

The first patch is for httpd.h, the second for mod_proxy.

Regards,
Graham
-- 
-----------------------------------------
[EMAIL PROTECTED]                "There's a moon
                                        over Bourbon Street
                                                tonight..."
diff -u3 -r --exclude=CVS ../../pristine/httpd-2.0/include/httpd.h 
httpd-2.0/include/httpd.h
--- ../../pristine/httpd-2.0/include/httpd.h    Tue Apr  3 20:09:24 2001
+++ httpd-2.0/include/httpd.h   Tue Apr 10 23:49:11 2001
@@ -834,6 +834,8 @@
     server_rec *base_server;
     /** used by http_vhost.c */
     void *vhost_lookup_data;
+    /** used by mod_proxy.c */
+    conn_rec *downstream;
 
     /* Information about the connection itself */
 
diff -u3 -r --exclude=CVS httpd-proxy2/module-2.0/proxy_http.c 
httpd-2.0/modules/proxy/proxy_http.c
--- httpd-proxy2/module-2.0/proxy_http.c        Tue Apr 10 23:27:28 2001
+++ httpd-2.0/modules/proxy/proxy_http.c        Wed Apr 11 01:10:32 2001
@@ -285,11 +285,12 @@
      * open, or whether it should be closed and a new socket created.
      */
     /* see memory note above */
-    if (conf->connection) {
-       if ((conf->id == c->id) &&
-           (conf->connectport == connectport) &&
-           (conf->connectname) &&
-            (!apr_strnatcasecmp(conf->connectname,connectname))) {
+    if (c->downstream) {
+        apr_port_t port = 0;
+       if ((c->downstream->id == c->id) &&
+           (APR_SUCCESS == apr_sockaddr_port_get(&port, c->downstream->remote_addr)) 
+&&
+           (port == connectport) &&
+            (!apr_strnatcasecmp(c->downstream->remote_host,connectname))) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
                         "proxy: keepalive address match (keep original socket)");
         }
@@ -297,20 +298,20 @@
             ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
                         "proxy: keepalive address mismatch / connection has"
                         " changed (close old socket (%s/%s, %d/%d))", 
-                        connectname, conf->connectname, 
-                        connectport, conf->connectport);
-            apr_socket_close(conf->connection->client_socket);
-            conf->connection = NULL;
+                        connectname, c->downstream->remote_host, 
+                        connectport, port);
+            apr_socket_close(c->downstream->client_socket);
+            c->downstream = NULL;
        }
     }
 
     /* get a socket - either a keepalive one, or a new one */
     new = 1;
-    if ((conf->id == c->id) && (conf->connection)) {
+    if ((c->downstream) && (c->downstream->id == c->id)) {
 
        /* use previous keepalive socket */
-       sock = conf->connection->client_socket;
-       origin = conf->connection;
+       origin = c->downstream;
+       sock = origin->client_socket;
        new = 0;
 
        /* reset the connection filters */
@@ -322,7 +323,7 @@
     if (new) {
 
        /* create a new socket */
-       conf->connection = NULL;
+       c->downstream = NULL;
 
        /* see memory note above */
        if ((apr_socket_create(&sock, APR_INET, SOCK_STREAM, c->pool)) != APR_SUCCESS) 
{
@@ -399,10 +400,8 @@
            apr_socket_close(sock);
            return HTTP_INTERNAL_SERVER_ERROR;
        }
-       conf->id = r->connection->id;
-       conf->connectname = connectname;
-       conf->connectport = connectport;
-       conf->connection = origin;
+       c->downstream = origin;
+       c->downstream->remote_host = apr_pstrdup(c->pool, connectname);
 
        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
                     "proxy: connection complete");
@@ -581,7 +580,7 @@
 
     if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, 
sizeof(buffer)))) {
        apr_socket_close(sock);
-       conf->connection = NULL;
+       c->downstream = NULL;
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
             "proxy: error reading status line from remote server %s",
             connectname);
@@ -602,7 +601,7 @@
         /* If not an HTTP/1 message or if the status line was > 8192 bytes */
        else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {
            apr_socket_close(sock);
-           conf->connection = NULL;
+           c->downstream = NULL;
            return ap_proxyerror(r, HTTP_BAD_GATEWAY,
                                 apr_pstrcat(p, "Corrupt status line returned by 
remote server: ", buffer, NULL));
        }
@@ -752,7 +751,7 @@
      */
     if (close || (r->proto_num < HTTP_VERSION(1,1))) {
         apr_socket_close(sock);
-       conf->connection = NULL;
+       c->downstream = NULL;
     }
 
     return OK;

Reply via email to