You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kg...@apache.org on 2020/10/15 18:08:20 UTC

[qpid-dispatch] branch dev-protocol-adaptors-2 updated: DISPATCH-1791: fix strdup and qdr_delivery_t leaks

This is an automated email from the ASF dual-hosted git repository.

kgiusti pushed a commit to branch dev-protocol-adaptors-2
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git


The following commit(s) were added to refs/heads/dev-protocol-adaptors-2 by this push:
     new 1ec325e  DISPATCH-1791: fix strdup and qdr_delivery_t leaks
1ec325e is described below

commit 1ec325e4b1cf0ae5c76bb5cfaa9b88566804a9fd
Author: Kenneth Giusti <kg...@apache.org>
AuthorDate: Wed Oct 14 16:03:50 2020 -0400

    DISPATCH-1791: fix strdup and qdr_delivery_t leaks
    
    This closes #882
---
 src/adaptors/http1/http1_adaptor.c | 35 ++++++++++++++++++++++++-------
 src/adaptors/http1/http1_client.c  |  4 ----
 src/adaptors/http1/http1_codec.c   |  1 +
 src/adaptors/http1/http1_private.h |  1 +
 src/adaptors/http1/http1_server.c  | 43 +++++++++++++++++++++++++-------------
 5 files changed, 58 insertions(+), 26 deletions(-)

diff --git a/src/adaptors/http1/http1_adaptor.c b/src/adaptors/http1/http1_adaptor.c
index e1fb155..4cdd44f 100644
--- a/src/adaptors/http1/http1_adaptor.c
+++ b/src/adaptors/http1/http1_adaptor.c
@@ -81,20 +81,36 @@ void qdr_http1_request_base_cleanup(qdr_http1_request_base_t *hreq)
 void qdr_http1_connection_free(qdr_http1_connection_t *hconn)
 {
     if (hconn) {
+        pn_raw_connection_t *rconn = 0;
+        qd_timer_t *t1 = 0;
+        qd_timer_t *t2 = 0;
 
+        // prevent core from activating this connection while it is being torn
+        // down.  see _core_connection_activate_CT
+        //
         sys_mutex_lock(qdr_http1_adaptor->lock);
-        DEQ_REMOVE(qdr_http1_adaptor->connections, hconn);
+        {
+            DEQ_REMOVE(qdr_http1_adaptor->connections, hconn);
+            t1 = hconn->server.reconnect_timer;
+            hconn->server.reconnect_timer = 0;
+            t2 = hconn->server.activate_timer;
+            hconn->server.activate_timer = 0;
+            rconn = hconn->raw_conn;
+            hconn->raw_conn = 0;
+        }
         sys_mutex_unlock(qdr_http1_adaptor->lock);
 
         // request expected to be clean up by caller
 #if 0  // JIRA ME!
         assert(DEQ_IS_EMPTY(hconn->requests));
 #endif
+        qd_timer_free(t1);
+        qd_timer_free(t2);
 
         h1_codec_connection_free(hconn->http_conn);
-        if (hconn->raw_conn) {
-            pn_raw_connection_set_context(hconn->raw_conn, 0);
-            pn_raw_connection_close(hconn->raw_conn);
+        if (rconn) {
+            pn_raw_connection_set_context(rconn, 0);
+            pn_raw_connection_close(rconn);
         }
 #if 0
         if (hconn->out_link) {
@@ -119,8 +135,6 @@ void qdr_http1_connection_free(qdr_http1_connection_t *hconn)
         free(hconn->client.client_ip_addr);
         free(hconn->client.reply_to_addr);
 
-        qd_timer_free(hconn->server.reconnect_timer);
-
         free_qdr_http1_connection_t(hconn);
     }
 }
@@ -425,12 +439,17 @@ static void _core_connection_activate_CT(void *context, qdr_connection_t *conn)
         if (hconn->raw_conn) {
             pn_raw_connection_wake(hconn->raw_conn);
             activated = true;
+        } else if (hconn->type == HTTP1_CONN_SERVER) {
+            if (hconn->server.activate_timer) {
+                qd_timer_schedule(hconn->server.activate_timer, 0);
+                activated = true;
+            }
         }
     }
     sys_mutex_unlock(qdr_http1_adaptor->lock);
 
-    if (hconn && activated)
-        qd_log(qdr_http1_adaptor->log, QD_LOG_DEBUG, "[C%"PRIu64"] Connection activate", hconn->conn_id);
+    qd_log(qdr_http1_adaptor->log, QD_LOG_DEBUG, "[C%"PRIu64"] Connection %s",
+           conn->identity, activated ? "activated" : "down, unable to activate");
 }
 
 
diff --git a/src/adaptors/http1/http1_client.c b/src/adaptors/http1/http1_client.c
index 3ad9ad6..e1096da 100644
--- a/src/adaptors/http1/http1_client.c
+++ b/src/adaptors/http1/http1_client.c
@@ -228,7 +228,6 @@ qd_http_lsnr_t *qd_http1_configure_listener(qd_dispatch_t *qd, const qd_http_bri
         return 0;
     }
     li->config = *config;
-
     DEQ_ITEM_INIT(li);
 
     sys_mutex_lock(qdr_http1_adaptor->lock);
@@ -506,7 +505,6 @@ static void _handle_connection_events(pn_event_t *e, qd_server_t *qd_server, voi
                 hconn->in_link_credit -= 1;
                 hreq->request_dlv = qdr_link_deliver(hconn->in_link, hreq->request_msg, 0, false, 0, 0, 0, 0);
                 qdr_delivery_set_context(hreq->request_dlv, (void*) hreq);
-                qdr_delivery_incref(hreq->request_dlv, "referenced by HTTP1 adaptor");
                 hreq->request_msg = 0;
             }
 
@@ -755,7 +753,6 @@ static int _client_rx_headers_done_cb(h1_codec_request_state_t *hrs, bool has_bo
 
         hreq->request_dlv = qdr_link_deliver(hconn->in_link, hreq->request_msg, 0, false, 0, 0, 0, 0);
         qdr_delivery_set_context(hreq->request_dlv, (void*) hreq);
-        qdr_delivery_incref(hreq->request_dlv, "referenced by HTTP1 adaptor");
         hreq->request_msg = 0;
     }
 
@@ -911,7 +908,6 @@ void qdr_http1_client_core_link_flow(qdr_http1_adaptor_t    *adaptor,
 
             hreq->request_dlv = qdr_link_deliver(hconn->in_link, hreq->request_msg, 0, false, 0, 0, 0, 0);
             qdr_delivery_set_context(hreq->request_dlv, (void*) hreq);
-            qdr_delivery_incref(hreq->request_dlv, "referenced by HTTP1 adaptor");
             hreq->request_msg = 0;
         }
     }
diff --git a/src/adaptors/http1/http1_codec.c b/src/adaptors/http1/http1_codec.c
index 7b63937..e1348d0 100644
--- a/src/adaptors/http1/http1_codec.c
+++ b/src/adaptors/http1/http1_codec.c
@@ -212,6 +212,7 @@ static void h1_codec_request_state_free(h1_codec_request_state_t *hrs)
         assert(conn->decoder.hrs != hrs);
         assert(conn->encoder.hrs != hrs);
         DEQ_REMOVE(conn->hrs_queue, hrs);
+        free(hrs->method);
         free_h1_codec_request_state_t(hrs);
     }
 }
diff --git a/src/adaptors/http1/http1_private.h b/src/adaptors/http1/http1_private.h
index 1e48146..ce10362 100644
--- a/src/adaptors/http1/http1_private.h
+++ b/src/adaptors/http1/http1_private.h
@@ -154,6 +154,7 @@ struct qdr_http1_connection_t {
 
     // State if connected to an HTTP server
     struct {
+        qd_timer_t *activate_timer;
         qd_timer_t *reconnect_timer;
         int         reconnect_count;
     } server;
diff --git a/src/adaptors/http1/http1_server.c b/src/adaptors/http1/http1_server.c
index 5c056f1..d76f343 100644
--- a/src/adaptors/http1/http1_server.c
+++ b/src/adaptors/http1/http1_server.c
@@ -114,6 +114,7 @@ static void _server_rx_done_cb(h1_codec_request_state_t *hrs);
 static void _server_request_complete_cb(h1_codec_request_state_t *hrs, bool cancelled);
 static void _handle_connection_events(pn_event_t *e, qd_server_t *qd_server, void *context);
 static void _do_reconnect(void *context);
+static void _do_activate(void *context);
 static void _server_response_msg_free(_server_request_t *req, _server_response_msg_t *rmsg);
 static void _server_request_free(_server_request_t *req);
 static void _server_connection_free(qdr_http1_connection_t *hconn);
@@ -150,6 +151,9 @@ static qdr_http1_connection_t *_create_server_connection(qd_http_connector_t *ct
     // for initiating a connection to the server
     hconn->server.reconnect_timer = qd_timer(qdr_http1_adaptor->core->qd, _do_reconnect, hconn);
 
+    // to run qdr_connection_process() when there is no raw connection to wake
+    hconn->server.activate_timer = qd_timer(qdr_http1_adaptor->core->qd, _do_activate, hconn);
+
     // Create the qdr_connection
 
     qdr_connection_info_t *info = qdr_connection_info(false, //bool             is_encrypted,
@@ -212,8 +216,9 @@ qd_http_connector_t *qd_http1_configure_connector(qd_dispatch_t *qd, const qd_ht
         qd_log(qdr_http1_adaptor->log, QD_LOG_ERROR, "Unable to create http connector: no memory");
         return 0;
     }
-
+    c->config = *config;
     DEQ_ITEM_INIT(c);
+
     qdr_http1_connection_t *hconn = _create_server_connection(c, qd, config);
     if (hconn) {
         sys_mutex_lock(qdr_http1_adaptor->lock);
@@ -376,6 +381,21 @@ static void _do_reconnect(void *context)
 }
 
 
+// This adapter attempts to keep the qdr_connection_t open as it tries to
+// re-connect to the server.  During this reconnect phase there is no raw
+// connection.  If the core needs to process the qdr_connection_t when there is
+// no raw connection to wake this zero-length timer handler will perform the
+// connection processing (under the I/O thread).
+//
+static void _do_activate(void *context)
+{
+    qdr_http1_connection_t *hconn = (qdr_http1_connection_t*) context;
+    if (hconn->qdr_conn) {
+        while (qdr_connection_process(hconn->qdr_conn)) {}
+    }
+}
+
+
 // Proton Raw Connection Events
 //
 static void _handle_connection_events(pn_event_t *e, qd_server_t *qd_server, void *context)
@@ -419,14 +439,12 @@ static void _handle_connection_events(pn_event_t *e, qd_server_t *qd_server, voi
             hconn->raw_conn = 0;
             _server_connection_free(hconn);
             return;
-        } else {
-            // prevent the core from activating this connection
-            // until we can re-establish it
-            sys_mutex_lock(qdr_http1_adaptor->lock);
-            hconn->raw_conn = 0;
-            sys_mutex_unlock(qdr_http1_adaptor->lock);
         }
 
+        sys_mutex_lock(qdr_http1_adaptor->lock);
+        hconn->raw_conn = 0;
+        sys_mutex_unlock(qdr_http1_adaptor->lock);
+
         // if the current request was not completed, cancel it.  it's ok if
         // there are outstanding *response* deliveries in flight as long as the
         // response(s) have been completely received from the server
@@ -835,7 +853,6 @@ static int _server_rx_headers_done_cb(h1_codec_request_state_t *hrs, bool has_bo
         qd_iterator_reset_view(addr, ITER_VIEW_ADDRESS_HASH);
         rmsg->dlv = qdr_link_deliver_to(hconn->in_link, rmsg->msg, 0, addr, false, 0, 0, 0, 0);
         qdr_delivery_set_context(rmsg->dlv, (void*) hreq);
-        qdr_delivery_incref(rmsg->dlv, "referenced by HTTP1 adaptor");
         rmsg->msg = 0;  // now owned by delivery
     }
 
@@ -992,17 +1009,15 @@ void qdr_http1_server_core_link_flow(qdr_http1_adaptor_t    *adaptor,
 
                 qd_iterator_t *addr = qd_message_field_iterator(rmsg->msg, QD_FIELD_TO);
                 qd_iterator_reset_view(addr, ITER_VIEW_ADDRESS_HASH);
-                qdr_delivery_t *dlv = qdr_link_deliver_to(hconn->in_link, rmsg->msg, 0, addr, false, 0, 0, 0, 0);
+                rmsg->dlv = qdr_link_deliver_to(hconn->in_link, rmsg->msg, 0, addr, false, 0, 0, 0, 0);
+                qdr_delivery_set_context(rmsg->dlv, (void*) hreq);
+                rmsg->msg = 0;
                 if (!rmsg->rx_complete) {
                     // stop here since response must be complete before we can deliver the next one.
-                    rmsg->dlv = dlv;
-                    qdr_delivery_set_context(rmsg->dlv, (void*) hreq);
-                    qdr_delivery_incref(rmsg->dlv, "referenced by HTTP1 adaptor");
-                    rmsg->msg = 0;
                     break;
                 }
 
-                // the delivery is complete no need to save it
+                // else the delivery is complete no need to save it
                 _server_response_msg_free(hreq, rmsg);
                 rmsg = DEQ_HEAD(hreq->responses);
             }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org