Author: rhuijben
Date: Sat Nov 28 23:58:58 2015
New Revision: 1717013

URL: http://svn.apache.org/viewvc?rev=1717013&view=rev
Log:
Add a protocol callback for a cleanup step before the requests are done.
This allows cleaning up writer state and thereby avoids segfaults when
buckets are destroyed out of order.

This should solve a segfault/abort() in the Subversion over H2 issue I'm
debugging.

* incoming.c
  (serf_incoming_set_framing_type,
   serf_incoming_create2): Hook pre teardown.

* outgoing.c
  (reset_connection,
   serf_connection_create,
   serf_connection_close,
   serf_connection_set_framing_type): Hook pre teardown.

* protocols/http2_protocol.c
  (http2_outgoing_pre_teardown,
   http2_incoming_pre_teardown): New prototypes.
  (serf__http2_protocol_init,
   serf__http2_protocol_init_server): Hook teardown.
  (http2_outgoing_pre_teardown,
   http2_incoming_pre_teardown): New function.

* protocols/http2_protocol.h
  (serf_http2__stream_pre_cleanup): New function.

* protocols/http2_stream.c
  (serf_http2__stream_pre_cleanup): New function. Destroy data tail here
    instead of...
  (serf_http2__stream_cleanup): ... here.

* serf_private.h
  (serf_incoming_t,
   serf_connection_t): New callback.

Modified:
    serf/trunk/incoming.c
    serf/trunk/outgoing.c
    serf/trunk/protocols/http2_protocol.c
    serf/trunk/protocols/http2_protocol.h
    serf/trunk/protocols/http2_stream.c
    serf/trunk/serf_private.h

Modified: serf/trunk/incoming.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/incoming.c?rev=1717013&r1=1717012&r2=1717013&view=diff
==============================================================================
--- serf/trunk/incoming.c (original)
+++ serf/trunk/incoming.c Sat Nov 28 23:58:58 2015
@@ -393,6 +393,8 @@ void serf_incoming_set_framing_type(
 
         /* Close down existing protocol */
         if (client->protocol_baton && client->perform_teardown) {
+            if (client->perform_pre_teardown)
+                client->perform_pre_teardown(client);
             client->perform_teardown(client);
             client->protocol_baton = NULL;
         }
@@ -402,6 +404,7 @@ void serf_incoming_set_framing_type(
         client->perform_write = write_to_client;
         client->perform_hangup = hangup_client;
         client->perform_teardown = NULL;
+        client->perform_pre_teardown = NULL;
 
         switch (framing_type) {
             case SERF_CONNECTION_FRAMING_TYPE_HTTP2:
@@ -591,6 +594,7 @@ apr_status_t serf_incoming_create2(
     ic->perform_write = write_to_client;
     ic->perform_hangup = hangup_client;
     ic->perform_teardown = NULL;
+    ic->perform_pre_teardown = NULL;
     ic->current_request = NULL;
 
     ic->desc.desc_type = APR_POLL_SOCKET;

Modified: serf/trunk/outgoing.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/outgoing.c?rev=1717013&r1=1717012&r2=1717013&view=diff
==============================================================================
--- serf/trunk/outgoing.c (original)
+++ serf/trunk/outgoing.c Sat Nov 28 23:58:58 2015
@@ -492,6 +492,9 @@ static apr_status_t reset_connection(ser
 
     serf__connection_pre_cleanup(conn);
 
+    if (conn->perform_pre_teardown)
+        conn->perform_pre_teardown(conn);
+
     /* First, cancel all written requests for which we haven't received a
        response yet. Inform the application that the request is cancelled,
        so it can requeue them if needed. */
@@ -564,6 +567,7 @@ static apr_status_t reset_connection(ser
     conn->perform_write = write_to_connection;
     conn->perform_hangup = hangup_connection;
     conn->perform_teardown = NULL;
+    conn->perform_pre_teardown = NULL;
     conn->perform_cancel_request = NULL;
     conn->perform_prioritize_request = NULL;
 
@@ -1248,6 +1252,7 @@ serf_connection_t *serf_connection_creat
     conn->perform_write = write_to_connection;
     conn->perform_hangup = hangup_connection;
     conn->perform_teardown = NULL;
+    conn->perform_pre_teardown = NULL;
     conn->perform_cancel_request = NULL;
     conn->perform_prioritize_request = NULL;
     conn->protocol_baton = NULL;
@@ -1359,6 +1364,9 @@ apr_status_t serf_connection_close(
                requests as fully written, allowing more efficient cleanup */
             serf__connection_pre_cleanup(conn);
 
+            if (conn->perform_pre_teardown)
+                conn->perform_pre_teardown(conn);
+
             /* The application asked to close the connection, no need to notify
                it for each cancelled request. */
             while (conn->written_reqs) {
@@ -1463,6 +1471,8 @@ void serf_connection_set_framing_type(
 
         /* Close down existing protocol */
         if (conn->protocol_baton) {
+            if (conn->perform_pre_teardown)
+                conn->perform_pre_teardown(conn);
             conn->perform_teardown(conn);
             conn->protocol_baton = NULL;
         }
@@ -1475,6 +1485,7 @@ void serf_connection_set_framing_type(
     conn->perform_cancel_request = NULL;
     conn->perform_prioritize_request = NULL;
     conn->perform_teardown = NULL;
+    conn->perform_pre_teardown = NULL;
 
     switch (framing_type) {
         case SERF_CONNECTION_FRAMING_TYPE_HTTP2:

Modified: serf/trunk/protocols/http2_protocol.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.c?rev=1717013&r1=1717012&r2=1717013&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.c (original)
+++ serf/trunk/protocols/http2_protocol.c Sat Nov 28 23:58:58 2015
@@ -43,6 +43,9 @@ http2_outgoing_hangup(serf_connection_t
 static void
 http2_outgoing_teardown(serf_connection_t *conn);
 
+static void
+http2_outgoing_pre_teardown(serf_connection_t *conn);
+
 static apr_status_t
 http2_incoming_read(serf_incoming_t *client);
 
@@ -55,6 +58,9 @@ http2_incoming_hangup(serf_incoming_t *c
 static void
 http2_incoming_teardown(serf_incoming_t *conn);
 
+static void
+http2_incoming_pre_teardown(serf_incoming_t *conn);
+
 static apr_status_t
 http2_process(serf_http2_protocol_t *h2);
 
@@ -345,6 +351,7 @@ void serf__http2_protocol_init(serf_conn
     conn->perform_write = http2_outgoing_write;
     conn->perform_hangup = http2_outgoing_hangup;
     conn->perform_teardown = http2_outgoing_teardown;
+    conn->perform_pre_teardown = http2_outgoing_pre_teardown;
     conn->perform_cancel_request = http2_cancel_request;
     conn->perform_prioritize_request = http2_prioritize_request;
     conn->protocol_baton = h2;
@@ -428,6 +435,7 @@ void serf__http2_protocol_init_server(se
     client->perform_write = http2_incoming_write;
     client->perform_hangup = http2_incoming_hangup;
     client->perform_teardown = http2_incoming_teardown;
+    client->perform_pre_teardown = http2_incoming_pre_teardown;
     client->protocol_baton = h2;
 
     /* Send a settings frame */
@@ -1706,6 +1714,18 @@ http2_outgoing_hangup(serf_connection_t
 }
 
 static void
+http2_outgoing_pre_teardown(serf_connection_t *conn)
+{
+    serf_http2_protocol_t *h2 = conn->protocol_baton;
+    serf_http2_stream_t *s = h2->first;
+
+    while (s) {
+        serf_http2__stream_pre_cleanup(s);
+        s = s->next;
+    }
+}
+
+static void
 http2_outgoing_teardown(serf_connection_t *conn)
 {
     serf_http2_protocol_t *ctx = conn->protocol_baton;
@@ -1843,6 +1863,19 @@ http2_incoming_teardown(serf_incoming_t
     client->protocol_baton = NULL;
 }
 
+static void
+http2_incoming_pre_teardown(serf_incoming_t *conn)
+{
+    serf_http2_protocol_t *h2 = conn->protocol_baton;
+    serf_http2_stream_t *s = h2->first;
+
+    while (s) {
+        serf_http2__stream_pre_cleanup(s);
+        s = s->next;
+    }
+}
+
+
 void
 serf_http2__allocate_stream_id(void *baton,
                                apr_int32_t *streamid)

Modified: serf/trunk/protocols/http2_protocol.h
URL: 
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.h?rev=1717013&r1=1717012&r2=1717013&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.h (original)
+++ serf/trunk/protocols/http2_protocol.h Sat Nov 28 23:58:58 2015
@@ -189,6 +189,10 @@ serf_http2__allocate_stream_id(void *bat
 void
 serf_http2__stream_cleanup(serf_http2_stream_t *stream);
 
+void
+serf_http2__stream_pre_cleanup(serf_http2_stream_t *stream);
+
+
 serf_http2_stream_t *
 serf_http2__stream_get(serf_http2_protocol_t *h2,
                        apr_int32_t streamid,

Modified: serf/trunk/protocols/http2_stream.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_stream.c?rev=1717013&r1=1717012&r2=1717013&view=diff
==============================================================================
--- serf/trunk/protocols/http2_stream.c (original)
+++ serf/trunk/protocols/http2_stream.c Sat Nov 28 23:58:58 2015
@@ -84,6 +84,15 @@ serf_http2__stream_create(serf_http2_pro
 }
 
 void
+serf_http2__stream_pre_cleanup(serf_http2_stream_t *stream)
+{
+    if (stream->data) {
+        if (stream->data->data_tail)
+            serf_bucket_destroy(stream->data->data_tail);
+    }
+}
+
+void
 serf_http2__stream_cleanup(serf_http2_stream_t *stream)
 {
     if (stream->data) {

Modified: serf/trunk/serf_private.h
URL: 
http://svn.apache.org/viewvc/serf/trunk/serf_private.h?rev=1717013&r1=1717012&r2=1717013&view=diff
==============================================================================
--- serf/trunk/serf_private.h (original)
+++ serf/trunk/serf_private.h Sat Nov 28 23:58:58 2015
@@ -458,6 +458,7 @@ struct serf_incoming_t {
     apr_status_t(*perform_hangup)(serf_incoming_t *client);
 
     /* Cleanup of protocol handling */
+    void(*perform_pre_teardown)(serf_incoming_t *conn);
     void(*perform_teardown)(serf_incoming_t *conn);
     void *protocol_baton;
 
@@ -575,6 +576,7 @@ struct serf_connection_t {
     apr_status_t (*perform_hangup)(serf_connection_t *conn);
 
     /* Cleanup of protocol handling */
+    void(*perform_pre_teardown)(serf_connection_t *conn);
     void (*perform_teardown)(serf_connection_t *conn);
     void *protocol_baton;
 


Reply via email to