You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by br...@apache.org on 2005/12/04 21:38:30 UTC

svn commit: r353904 - in /httpd/httpd/branches/async-read-dev: include/http_protocol.h include/httpd.h modules/http/http_core.c server/protocol.c

Author: brianp
Date: Sun Dec  4 12:38:25 2005
New Revision: 353904

URL: http://svn.apache.org/viewcvs?rev=353904&view=rev
Log:
Added ap_read_async_request()...
At the moment, asynchronous MPMs still read the request headers
with the connection in blocking mode.  To enable asynchronous
read completion, we'll need to make some changes in the Event MPM.


Modified:
    httpd/httpd/branches/async-read-dev/include/http_protocol.h
    httpd/httpd/branches/async-read-dev/include/httpd.h
    httpd/httpd/branches/async-read-dev/modules/http/http_core.c
    httpd/httpd/branches/async-read-dev/server/protocol.c

Modified: httpd/httpd/branches/async-read-dev/include/http_protocol.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-read-dev/include/http_protocol.h?rev=353904&r1=353903&r2=353904&view=diff
==============================================================================
--- httpd/httpd/branches/async-read-dev/include/http_protocol.h (original)
+++ httpd/httpd/branches/async-read-dev/include/http_protocol.h Sun Dec  4 12:38:25 2005
@@ -62,6 +62,16 @@
 request_rec *ap_read_request(conn_rec *c);
 
 /**
+ * Read part or all of a request and fill in the fields.
+ * @param c The current connection
+ * @return APR_SUCCESS if the request header is completely read,
+ *         APR_EAGAIN if the caller should wait for readability on
+ *         the connection and try again, arbirary other apr_status_t
+ *         values if the read fails for any other reason
+ */ 
+apr_status_t ap_read_async_request(conn_rec *c);
+
+/**
  * Read the mime-encoded headers.
  * @param r The current request
  */

Modified: httpd/httpd/branches/async-read-dev/include/httpd.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-read-dev/include/httpd.h?rev=353904&r1=353903&r2=353904&view=diff
==============================================================================
--- httpd/httpd/branches/async-read-dev/include/httpd.h (original)
+++ httpd/httpd/branches/async-read-dev/include/httpd.h Sun Dec  4 12:38:25 2005
@@ -1078,6 +1078,9 @@
     int data_in_input_filters;
     /** Is there data pending in the output filters? */
     int data_in_output_filters;
+    /** The request (possibly incomplete) currently being processed
+     *  on this connection, or NULL if not applicable */
+    request_rec *request;
 };
 
 /** 

Modified: httpd/httpd/branches/async-read-dev/modules/http/http_core.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-read-dev/modules/http/http_core.c?rev=353904&r1=353903&r2=353904&view=diff
==============================================================================
--- httpd/httpd/branches/async-read-dev/modules/http/http_core.c (original)
+++ httpd/httpd/branches/async-read-dev/modules/http/http_core.c Sun Dec  4 12:38:25 2005
@@ -108,42 +108,36 @@
 
 static int ap_process_http_async_connection(conn_rec *c)
 {
-    request_rec *r;
+    apr_status_t rv;
     conn_state_t *cs = c->cs;
 
     AP_DEBUG_ASSERT(cs->state == CONN_STATE_READ_REQUEST_LINE);
 
-    while (cs->state == CONN_STATE_READ_REQUEST_LINE) {
-        ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL);
-
-        if ((r = ap_read_request(c))) {
-
-            c->keepalive = AP_CONN_UNKNOWN;
-            /* process the request if it was read without error */
+    ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL);
 
-            ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
-            if (r->status == HTTP_OK) {
-                cs->state = CONN_STATE_HANDLER;
-                ap_process_async_request(r);
-                /* After the call to ap_process_request, the
-                 * request pool may have been deleted.  We set
-                 * r=NULL here to ensure that any dereference
-                 * of r that might be added later in this function
-                 * will result in a segfault immediately instead
-                 * of nondeterministic failures later.
-                 */
-                r = NULL;
-            }
-
-            if (cs->state != CONN_STATE_WRITE_COMPLETION) {
-                /* Something went wrong; close the connection */
-                cs->state = CONN_STATE_LINGER;
-            }
+    rv = ap_read_async_request(c);
+    if (rv == APR_SUCCESS) {
+        c->keepalive = AP_CONN_UNKNOWN;
+        /* process the request if it was read without error */
+        ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, c->request);
+        if (c->request->status == HTTP_OK) {
+            cs->state = CONN_STATE_HANDLER;
+            ap_process_async_request(c->request);
+            c->request = NULL;
         }
-        else {   /* ap_read_request failed - client may have closed */
+
+        if (cs->state != CONN_STATE_WRITE_COMPLETION) {
+            /* Something went wrong; close the connection */
             cs->state = CONN_STATE_LINGER;
         }
     }
+    else if (!APR_STATUS_IS_EAGAIN(rv)) {
+        /* EAGAIN means that we've successfully read a partial request
+         * header, which is valid in an async server.  For any other error,
+         * close the connection.
+         */
+        cs->state = CONN_STATE_LINGER;
+    }
 
     return OK;
 }
@@ -164,11 +158,12 @@
 
         c->keepalive = AP_CONN_UNKNOWN;
         /* process the request if it was read without error */
-
+        c->request = r;
         ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
         if (r->status == HTTP_OK) {
             cs->state = CONN_STATE_HANDLER;
             ap_process_request(r);
+            c->request = NULL;
             /* After the call to ap_process_request, the
              * request pool will have been deleted.  We set
              * r=NULL here to ensure that any dereference

Modified: httpd/httpd/branches/async-read-dev/server/protocol.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/async-read-dev/server/protocol.c?rev=353904&r1=353903&r2=353904&view=diff
==============================================================================
--- httpd/httpd/branches/async-read-dev/server/protocol.c (original)
+++ httpd/httpd/branches/async-read-dev/server/protocol.c Sun Dec  4 12:38:25 2005
@@ -1002,6 +1002,55 @@
     return rv;
 }
 
+AP_DECLARE(apr_status_t) ap_read_async_request(conn_rec *conn)
+{
+    apr_status_t rv;
+    request_rec *r;
+
+    if (conn->request == NULL) {
+        conn->request = init_request(conn);
+        if (conn->request == NULL) {
+            return APR_EGENERAL;
+        }
+    }
+
+    r = conn->request;
+    rv = read_partial_request(r);
+    if (APR_STATUS_IS_EAGAIN(rv)) {
+        return APR_EAGAIN;
+    }
+    if (r->status != HTTP_OK) {
+        ap_send_error_response(r, 0);
+        ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+        ap_run_log_transaction(r);
+        return APR_EGENERAL;
+    }
+
+    if (r->assbackwards && r->header_only) {
+        /*
+         * Client asked for headers only with HTTP/0.9, which doesn't send
+         * headers! Have to dink things just to make sure the error message
+         * comes through...
+         */
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                      "client sent invalid HTTP/0.9 request: HEAD %s",
+                      r->uri);
+        r->header_only = 0;
+        r->status = HTTP_BAD_REQUEST;
+        ap_send_error_response(r, 0);
+        ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+        ap_run_log_transaction(r);
+        return APR_EGENERAL;
+    }
+
+    if (request_post_read(r, conn) == NULL) {
+        return APR_EGENERAL;
+    }
+    else {
+        return APR_SUCCESS;
+    }
+}
+
 request_rec *ap_read_request(conn_rec *conn)
 {
     request_rec *r;
@@ -1010,7 +1059,6 @@
     r = init_request(conn);
 
     rv = read_partial_request(r);
-    /* TODO poll if EAGAIN */
     if (r->status != HTTP_OK) {
         ap_send_error_response(r, 0);
         ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);