]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
more good things from trunk
authorStefan Eissing <icing@apache.org>
Mon, 26 Oct 2015 15:58:38 +0000 (15:58 +0000)
committerStefan Eissing <icing@apache.org>
Mon, 26 Oct 2015 15:58:38 +0000 (15:58 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4-http2-alpha@1710636 13f79535-47bb-0310-9956-ffa450edef68

modules/http2/h2_conn.c
modules/http2/h2_h2.c
modules/http2/h2_io.c
modules/http2/h2_mplx.c
modules/http2/h2_session.c
modules/http2/h2_session.h
modules/http2/h2_stream.h
modules/http2/h2_version.h

index 1cb3234ca1f9de2ebc7f4b326f0f4b28e776b865..9794699f8844870fe2bff1349d103460ab3f3c21 100644 (file)
@@ -39,7 +39,7 @@
 
 static struct h2_workers *workers;
 
-static apr_status_t h2_session_process(h2_session *session);
+static apr_status_t h2_conn_loop(h2_session *session);
 
 static h2_mpm_type_t mpm_type = H2_MPM_UNKNOWN;
 static module *mpm_module;
@@ -156,7 +156,7 @@ apr_status_t h2_conn_rprocess(request_rec *r)
         return APR_EGENERAL;
     }
     
-    return h2_session_process(session);
+    return h2_conn_loop(session);
 }
 
 apr_status_t h2_conn_main(conn_rec *c)
@@ -177,7 +177,7 @@ apr_status_t h2_conn_main(conn_rec *c)
         return APR_EGENERAL;
     }
     
-    status = h2_session_process(session);
+    status = h2_conn_loop(session);
 
     /* Make sure this connection gets closed properly. */
     c->keepalive = AP_CONN_CLOSE;
@@ -188,7 +188,7 @@ apr_status_t h2_conn_main(conn_rec *c)
     return status;
 }
 
-apr_status_t h2_session_process(h2_session *session)
+static apr_status_t h2_conn_loop(h2_session *session)
 {
     apr_status_t status = APR_SUCCESS;
     int rv = 0;
@@ -283,10 +283,19 @@ apr_status_t h2_session_process(h2_session *session)
          *     submit our settings and need the ACK.
          */
         got_streams = !h2_stream_set_is_empty(session->streams);
-        status = h2_session_read(session, 
-                                 (!got_streams 
-                                  || session->frames_received <= 1)?
-                                 APR_BLOCK_READ : APR_NONBLOCK_READ);
+        if (!got_streams || session->frames_received <= 1) {
+            if (session->c->cs) {
+                session->c->cs->state = CONN_STATE_WRITE_COMPLETION;
+            }
+            status = h2_session_read(session, APR_BLOCK_READ);
+        }
+        else {
+            if (session->c->cs) {
+                session->c->cs->state = CONN_STATE_HANDLER;
+            }
+            status = h2_session_read(session, APR_NONBLOCK_READ);
+        }
+        
         switch (status) {
             case APR_SUCCESS:       /* successful read, reset our idle timers */
                 have_read = 1;
@@ -294,21 +303,28 @@ apr_status_t h2_session_process(h2_session *session)
                 break;
             case APR_EAGAIN:              /* non-blocking read, nothing there */
                 break;
-            case APR_EBADF:               /* connection is not there any more */
-            case APR_EOF:
-            case APR_ECONNABORTED:
-            case APR_ECONNRESET:
-            case APR_TIMEUP:                       /* blocked read, timed out */
-                ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
-                              "h2_session(%ld): reading",
-                              session->id);
-                h2_session_abort(session, status, 0);
-                break;
             default:
-                ap_log_cerror( APLOG_MARK, APLOG_INFO, status, session->c,
-                              APLOGNO(02950) 
-                              "h2_session(%ld): error reading, terminating",
-                              session->id);
+                if (APR_STATUS_IS_ETIMEDOUT(status)
+                    || APR_STATUS_IS_ECONNABORTED(status)
+                    || APR_STATUS_IS_ECONNRESET(status)
+                    || APR_STATUS_IS_EOF(status)
+                    || APR_STATUS_IS_EBADF(status)) {
+                    /* common status for a client that has left */
+                    ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
+                                  "h2_session(%ld): terminating",
+                                  session->id);
+                    /* Stolen from mod_reqtimeout to speed up lingering when
+                     * a read timeout happened.
+                     */
+                    apr_table_setn(session->c->notes, "short-lingering-close", "1");
+                }
+                else {
+                    /* uncommon status, log on INFO so that we see this */
+                    ap_log_cerror( APLOG_MARK, APLOG_INFO, status, session->c,
+                                  APLOGNO(02950) 
+                                  "h2_session(%ld): error reading, terminating",
+                                  session->id);
+                }
                 h2_session_abort(session, status, 0);
                 break;
         }
@@ -471,7 +487,6 @@ apr_status_t h2_conn_process(conn_rec *c, apr_socket_t *socket)
 {
     AP_DEBUG_ASSERT(c);
     
-    c->clogging_input_filters = 1;
     ap_process_connection(c, socket);
     
     return APR_SUCCESS;
index 221f5118df9eba4844e05d3cf45e8669a60a4cbc..ac460ef899fe7be8d7d443482002be570e5c3c59 100644 (file)
@@ -94,6 +94,7 @@ int h2_tls_disable(conn_rec *c)
     return 0;
 }
 
+
 /*******************************************************************************
  * Register various hooks
  */
@@ -119,7 +120,7 @@ void h2_h2_register_hooks(void)
     ap_hook_post_read_request(h2_h2_post_read_req, NULL, NULL, APR_HOOK_REALLY_FIRST);
 }
 
-int h2_h2_remove_timeout(conn_rec* c)
+static int h2_h2_remove_timeout(conn_rec* c)
 {
     h2_ctx *ctx = h2_ctx_get(c);
     
index 9f699aa9b530cc9b23b80d0c9081cb29983700a5..93bcca86085b7da64e6fccaa83e28d4ce778391d 100644 (file)
@@ -80,6 +80,10 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb,
     apr_bucket *last;
     apr_status_t status;
 
+    if (io->rst_error) {
+        return APR_ECONNABORTED;
+    }
+    
     if (!io->bbin || APR_BRIGADE_EMPTY(io->bbin)) {
         return io->eos_in? APR_EOF : APR_EAGAIN;
     }
@@ -102,6 +106,10 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb,
 
 apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb)
 {
+    if (io->rst_error) {
+        return APR_ECONNABORTED;
+    }
+    
     if (io->eos_in) {
         return APR_EOF;
     }
@@ -118,6 +126,10 @@ apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb)
 
 apr_status_t h2_io_in_close(h2_io *io)
 {
+    if (io->rst_error) {
+        return APR_ECONNABORTED;
+    }
+    
     if (io->bbin) {
         APR_BRIGADE_INSERT_TAIL(io->bbin, 
                                 apr_bucket_eos_create(io->bbin->bucket_alloc));
@@ -132,6 +144,10 @@ apr_status_t h2_io_out_readx(h2_io *io,
 {
     apr_status_t status;
     
+    if (io->rst_error) {
+        return APR_ECONNABORTED;
+    }
+    
     if (io->eos_out) {
         *plen = 0;
         *peos = 1;
@@ -158,6 +174,10 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb,
     apr_status_t status;
     int start_allowed;
     
+    if (io->rst_error) {
+        return APR_ECONNABORTED;
+    }
+
     if (io->eos_out) {
         apr_off_t len;
         /* We have already delivered an EOS bucket to a reader, no
@@ -188,9 +208,6 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb,
      */
     start_allowed = *pfile_handles_allowed;
 
-    if (io->rst_error) {
-        return APR_ECONNABORTED;
-    }
     status = h2_util_move(io->bbout, bb, maxlen, pfile_handles_allowed, 
                           "h2_io_out_write");
     /* track # file buckets moved into our pool */
@@ -203,6 +220,9 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb,
 
 apr_status_t h2_io_out_close(h2_io *io)
 {
+    if (io->rst_error) {
+        return APR_ECONNABORTED;
+    }
     if (!io->eos_out && !h2_util_has_eos(io->bbout, 0)) {
         APR_BRIGADE_INSERT_TAIL(io->bbout, 
                                 apr_bucket_eos_create(io->bbout->bucket_alloc));
index b1513db10e3d7b5b48d378066bacfa6399dfa506..ae33766e4ac30bd783aa9ada52c373ca1402114e 100644 (file)
@@ -29,6 +29,7 @@
 #include "h2_private.h"
 #include "h2_config.h"
 #include "h2_conn.h"
+#include "h2_h2.h"
 #include "h2_io.h"
 #include "h2_io_set.h"
 #include "h2_response.h"
@@ -288,18 +289,21 @@ apr_status_t h2_mplx_cleanup_stream(h2_mplx *m, h2_stream *stream)
     status = apr_thread_mutex_lock(m->lock);
     if (APR_SUCCESS == status) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream->id);
-        if (!io || io->task_done) {
-            /* No more io or task already done -> cleanup immediately */
-            stream_destroy(m, stream, io);
-        }
-        else {
+        if (io) {
+            /* Remove io from ready set, we will never submit it */
+            h2_io_set_remove(m->ready_ios, io);
             if (stream->rst_error) {
                 /* Forward error code to fail any further attempt to
                  * write to io */
                 h2_io_rst(io, stream->rst_error);
             }
-            /* Remove io from ready set (if there), since we will never submit it */
-            h2_io_set_remove(m->ready_ios, io);
+        }
+        
+        if (!io || io->task_done) {
+            /* No more io or task already done -> cleanup immediately */
+            stream_destroy(m, stream, io);
+        }
+        else {
             /* Add stream to closed set for cleanup when task is done */
             h2_stream_set_add(m->closed, stream);
         }
@@ -515,18 +519,21 @@ h2_stream *h2_mplx_next_submit(h2_mplx *m, h2_stream_set *streams)
                     h2_stream_set_response(stream, io->response, io->bbout);
                 }
                 
-                if (io->output_drained) {
-                    apr_thread_cond_signal(io->output_drained);
-                }
             }
             else {
-                ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(02953) 
-                              "h2_mplx(%ld): stream for response %d not found",
-                              m->id, io->id);
                 /* We have the io ready, but the stream has gone away, maybe
                  * reset by the client. Should no longer happen since such
                  * streams should clear io's from the ready queue.
                  */
+                ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c, APLOGNO(02953) 
+                              "h2_mplx(%ld): stream for response %d closed, "
+                              "resetting io to close request processing",
+                              m->id, io->id);
+                h2_io_rst(io, NGHTTP2_ERR_STREAM_CLOSED);
+            }
+            
+            if (io->output_drained) {
+                apr_thread_cond_signal(io->output_drained);
             }
         }
         apr_thread_mutex_unlock(m->lock);
index d8a8735afac45c583905a20b6af5637259334a41..fe567137de13b17d1e2e6a9b87c8915ae452f76f 100644 (file)
@@ -168,7 +168,7 @@ static int on_data_chunk_recv_cb(nghttp2_session *ngh2, uint8_t flags,
                   session->id, stream_id, (int)len);
     if (status != APR_SUCCESS) {
         rv = nghttp2_submit_rst_stream(ngh2, NGHTTP2_FLAG_NONE, stream_id,
-                                       NGHTTP2_INTERNAL_ERROR);
+                                       H2_STREAM_RST(stream, NGHTTP2_INTERNAL_ERROR));
         if (nghttp2_is_fatal(rv)) {
             return NGHTTP2_ERR_CALLBACK_FAILURE;
         }
@@ -931,17 +931,18 @@ apr_status_t h2_session_write(h2_session *session, apr_interval_time_t timeout)
     }
     
     /* If we have responses ready, submit them now. */
-    while ((stream = h2_mplx_next_submit(session->mplx, 
-                                         session->streams)) != NULL) {
+    while (!session->aborted 
+           && (stream = h2_mplx_next_submit(session->mplx, session->streams)) != NULL) {
         status = h2_session_handle_response(session, stream);
         flush_output = 1;
     }
     
-    if (h2_session_resume_streams_with_data(session) > 0) {
+    if (!session->aborted && h2_session_resume_streams_with_data(session) > 0) {
         flush_output = 1;
     }
     
-    if (!flush_output && timeout > 0 && !h2_session_want_write(session)) {
+    if (!session->aborted && !flush_output 
+        && timeout > 0 && !h2_session_want_write(session)) {
         status = h2_mplx_out_trywait(session->mplx, timeout, session->iowait);
 
         if (status != APR_TIMEUP
@@ -1151,13 +1152,10 @@ apr_status_t h2_session_handle_response(h2_session *session, h2_stream *stream)
     if (stream->response && stream->response->ngheader) {
         rv = submit_response(session, stream->response);
     }
-    else if (stream->rst_error) {
-        rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE,
-                                       stream->id, stream->rst_error);
-    }
     else {
         rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE,
-                                       stream->id, NGHTTP2_PROTOCOL_ERROR);
+                                       stream->id, 
+                                       H2_STREAM_RST(stream, NGHTTP2_PROTOCOL_ERROR));
     }
     
     if (nghttp2_is_fatal(rv)) {
@@ -1179,27 +1177,6 @@ int h2_session_is_done(h2_session *session)
                 && !nghttp2_session_want_write(session->ngh2)));
 }
 
-static int log_stream(void *ctx, h2_stream *stream)
-{
-    h2_session *session = (h2_session *)ctx;
-    AP_DEBUG_ASSERT(session);
-    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
-                  "h2_stream(%ld-%d): in set, suspended=%d, aborted=%d, "
-                  "has_data=%d",
-                  session->id, stream->id, stream->suspended, stream->aborted,
-                  h2_mplx_out_has_data_for(session->mplx, stream->id));
-    return 1;
-}
-
-void h2_session_log_stats(h2_session *session)
-{
-    AP_DEBUG_ASSERT(session);
-    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
-                  "h2_session(%ld): %d open streams",
-                  session->id, (int)h2_stream_set_size(session->streams));
-    h2_stream_set_iter(session->streams, log_stream, session);
-}
-
 static int frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen)
 {
     char scratch[128];
index 12768a90fb374e6e157a112fcf4889be98b650bb..ddf29a06df1316910655df13b1ab6a958886d6b2 100644 (file)
@@ -158,6 +158,4 @@ apr_status_t h2_session_handle_response(h2_session *session,
 /* Get the h2_stream for the given stream idenrtifier. */
 struct h2_stream *h2_session_get_stream(h2_session *session, int stream_id);
 
-void h2_session_log_stats(h2_session *session);
-
 #endif /* defined(__mod_h2__h2_session__) */
index c2bb9af74949dc78efe43e39db7143e36539be0c..f885bc439f901a927f68a6b7ca451304eab509f5 100644 (file)
@@ -70,6 +70,8 @@ struct h2_stream {
 };
 
 
+#define H2_STREAM_RST(s, def)    (s->rst_error? s->rst_error : (def))
+
 h2_stream *h2_stream_create(int id, apr_pool_t *pool, struct h2_mplx *m);
 
 apr_status_t h2_stream_destroy(h2_stream *stream);
index dc7c57722113cce848c77f16ad94d09e1ad8cbb4..10219daf1918fbe1115ecb43570fb4bb8586c8ac 100644 (file)
@@ -20,7 +20,7 @@
  * @macro
  * Version number of the h2 module as c string
  */
-#define MOD_HTTP2_VERSION "1.0.1-DEV"
+#define MOD_HTTP2_VERSION "1.0.2-DEV"
 
 /**
  * @macro
@@ -28,7 +28,7 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define MOD_HTTP2_VERSION_NUM 0x010001
+#define MOD_HTTP2_VERSION_NUM 0x010002
 
 
 #endif /* mod_h2_h2_version_h */