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;