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

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


The following commit(s) were added to refs/heads/master by this push:
     new 11756ad  DISPATCH-1214: remove shutdown leak of references reported by 
Valgrind
11756ad is described below

commit 11756ad277c571f75dcea26f2819211097a7d478
Author: Kenneth Giusti <kgiu...@apache.org>
AuthorDate: Tue Jan 15 16:04:53 2019 -0500

    DISPATCH-1214: remove shutdown leak of references reported by Valgrind
    
    This closes #439
---
 src/router_core/connections.c   | 12 +++++++++-
 src/router_core/route_control.c | 38 +++----------------------------
 src/router_core/route_control.h |  1 +
 src/router_core/router_core.c   | 50 ++++++++++++++++++++++++++++++++++++++---
 4 files changed, 62 insertions(+), 39 deletions(-)

diff --git a/src/router_core/connections.c b/src/router_core/connections.c
index 155a469..6184f52 100644
--- a/src/router_core/connections.c
+++ b/src/router_core/connections.c
@@ -855,13 +855,22 @@ static void qdr_link_cleanup_CT(qdr_core_t *core, 
qdr_connection_t *conn, qdr_li
     qdr_link_cleanup_deliveries_CT(core, conn, link);
 
     //
-    // Remove the reference to this link in the connection's reference lists
+    // Remove all references to this link in the connection's and owning
+    // address reference lists
     //
     sys_mutex_lock(conn->work_lock);
     qdr_del_link_ref(&conn->links, link, QDR_LINK_LIST_CLASS_CONNECTION);
     qdr_del_link_ref(conn->links_with_work + link->priority, link, 
QDR_LINK_LIST_CLASS_WORK);
     sys_mutex_unlock(conn->work_lock);
 
+    if (link->ref[QDR_LINK_LIST_CLASS_ADDRESS]) {
+        assert(link->owning_addr);
+        qdr_del_link_ref((link->link_direction == QD_OUTGOING)
+                         ? &link->owning_addr->rlinks
+                         : &link->owning_addr->inlinks,
+                         link,  QDR_LINK_LIST_CLASS_ADDRESS);
+    }
+
     //
     // Free the link's name and terminus_addr
     //
@@ -1256,6 +1265,7 @@ static void qdr_detach_link_control_CT(qdr_core_t *core, 
qdr_connection_t *conn,
 {
     if (conn->role == QDR_ROLE_INTER_ROUTER) {
         qdr_del_link_ref(&core->hello_addr->rlinks, link, 
QDR_LINK_LIST_CLASS_ADDRESS);
+        link->owning_addr = 0;
         core->control_links_by_mask_bit[conn->mask_bit] = 0;
         qdr_post_link_lost_CT(core, conn->mask_bit);
     }
diff --git a/src/router_core/route_control.c b/src/router_core/route_control.c
index 30cfb44..4810b98 100644
--- a/src/router_core/route_control.c
+++ b/src/router_core/route_control.c
@@ -91,7 +91,7 @@ static qdr_conn_identifier_t 
*qdr_route_declare_id_CT(qdr_core_t    *core,
 }
 
 
-static void qdr_route_check_id_for_deletion_CT(qdr_core_t *core, 
qdr_conn_identifier_t *cid)
+void qdr_route_check_id_for_deletion_CT(qdr_core_t *core, 
qdr_conn_identifier_t *cid)
 {
     //
     // If this connection identifier has no open connection and no referencing 
routes,
@@ -428,8 +428,7 @@ void qdr_route_auto_link_closed_CT(qdr_core_t *core, 
qdr_link_t *link)
 void qdr_route_del_link_route_CT(qdr_core_t *core, qdr_link_route_t *lr)
 {
     //
-    // Disassociate from the connection identifier.  Check to see if the 
identifier
-    // should be removed.
+    // Deactivate the link route on all connections
     //
     qdr_conn_identifier_t *cid = lr->conn_id;
     if (cid) {
@@ -438,19 +437,9 @@ void qdr_route_del_link_route_CT(qdr_core_t *core, 
qdr_link_route_t *lr)
             qdr_link_route_deactivate_CT(core, lr, cref->conn);
             cref = DEQ_NEXT(cref);
         }
-        DEQ_REMOVE_N(REF, cid->link_route_refs, lr);
-        qdr_route_check_id_for_deletion_CT(core, cid);
     }
 
     //
-    // Disassociate the link route from its address.  Check to see if the 
address
-    // (and its associated pattern) should be removed.
-    //
-    qdr_address_t *addr = lr->addr;
-    if (addr && --addr->ref_count == 0)
-        qdr_check_addr_CT(core, addr);
-
-    //
     // Remove the link route from the core list.
     //
     DEQ_REMOVE(core->link_routes, lr);
@@ -541,26 +530,13 @@ void qdr_route_del_auto_link_CT(qdr_core_t *core, 
qdr_auto_link_t *al)
             qdr_auto_link_deactivate_CT(core, al, cref->conn);
             cref = DEQ_NEXT(cref);
         }
-        DEQ_REMOVE_N(REF, cid->auto_link_refs, al);
-        qdr_route_check_id_for_deletion_CT(core, cid);
     }
 
     //
-    // Disassociate the auto link from its address.  Check to see if the 
address
-    // should be removed.
-    //
-    qdr_address_t *addr = al->addr;
-    if (addr && --addr->ref_count == 0)
-        qdr_check_addr_CT(core, addr);
-
-    //
     // Remove the auto link from the core list.
     //
     DEQ_REMOVE(core->auto_links, al);
-    free(al->name);
-    free(al->external_addr);
-    qdr_core_timer_free_CT(core, al->retry_timer);
-    free_qdr_auto_link_t(al);
+    qdr_core_delete_auto_link(core, al);
 }
 
 
@@ -755,14 +731,6 @@ void qdr_route_del_conn_route_CT(qdr_core_t       *core,
     qdr_link_route_deactivate_CT(core, lr, conn);
 
     //
-    // Disassociate the link route from its address.  Check to see if the 
address
-    // (and its associated pattern) should be removed.
-    //
-    qdr_address_t *addr = lr->addr;
-    if (addr && --addr->ref_count == 0)
-        qdr_check_addr_CT(core, addr);
-
-    //
     // Remove the link route from the parent's link route list
     //
     DEQ_REMOVE(conn->conn_link_routes, lr);
diff --git a/src/router_core/route_control.h b/src/router_core/route_control.h
index 7d893a3..8a1039b 100644
--- a/src/router_core/route_control.h
+++ b/src/router_core/route_control.h
@@ -54,6 +54,7 @@ void qdr_route_connection_closed_CT(qdr_core_t *core, 
qdr_connection_t *conn);
 
 void qdr_link_route_map_pattern_CT(qdr_core_t *core, qd_iterator_t *address, 
qdr_address_t *addr);
 void qdr_link_route_unmap_pattern_CT(qdr_core_t *core, qd_iterator_t *address);
+void qdr_route_check_id_for_deletion_CT(qdr_core_t *core, 
qdr_conn_identifier_t *cid);
 
 /**
  * Actions to be performed when an auto link detaches.
diff --git a/src/router_core/router_core.c b/src/router_core/router_core.c
index 7a9a8ee..6d458fe 100644
--- a/src/router_core/router_core.c
+++ b/src/router_core/router_core.c
@@ -116,7 +116,6 @@ void qdr_core_free(qdr_core_t *core)
     sys_mutex_free(core->id_lock);
     qd_timer_free(core->work_timer);
 
-
     //we can't call qdr_core_unsubscribe on the subscriptions because the 
action processing thread has
     //already been shut down. But, all the action would have done at this 
point is free the subscriptions
     //so we just do that directly.
@@ -155,8 +154,6 @@ void qdr_core_free(qdr_core_t *core)
     qd_parse_tree_free(core->addr_parse_tree);
     qd_parse_tree_free(core->link_route_tree[QD_INCOMING]);
     qd_parse_tree_free(core->link_route_tree[QD_OUTGOING]);
-    qd_hash_free(core->conn_id_hash);
-    //TODO what about the actual connection identifier objects?
 
     qdr_node_t *rnode = 0;
     while ( (rnode = DEQ_HEAD(core->routers)) ) {
@@ -166,6 +163,8 @@ void qdr_core_free(qdr_core_t *core)
     qdr_link_t *link = DEQ_HEAD(core->open_links);
     while (link) {
         DEQ_REMOVE_HEAD(core->open_links);
+        qdr_del_link_ref(&link->conn->links, link, 
QDR_LINK_LIST_CLASS_CONNECTION);
+        qdr_del_link_ref(&link->conn->links_with_work[link->priority], link, 
QDR_LINK_LIST_CLASS_WORK);
         free(link->name);
         free(link->disambiguated_name);
         free(link->terminus_addr);
@@ -180,10 +179,17 @@ void qdr_core_free(qdr_core_t *core)
     qdr_connection_t *conn = DEQ_HEAD(core->open_connections);
     while (conn) {
         DEQ_REMOVE_HEAD(core->open_connections);
+        if (conn->conn_id) {
+            qdr_del_connection_ref(&conn->conn_id->connection_refs, conn);
+            qdr_route_check_id_for_deletion_CT(core, conn->conn_id);
+        }
         qdr_connection_free(conn);
         conn = DEQ_HEAD(core->open_connections);
     }
 
+    // at this point all the conn identifiers have been freed
+    qd_hash_free(core->conn_id_hash);
+
     if (core->query_lock)                sys_mutex_free(core->query_lock);
     if (core->routers_by_mask_bit)       free(core->routers_by_mask_bit);
     if (core->control_links_by_mask_bit) free(core->control_links_by_mask_bit);
@@ -411,6 +417,17 @@ bool qdr_is_addr_treatment_multicast(qdr_address_t *addr)
 
 void qdr_core_delete_link_route(qdr_core_t *core, qdr_link_route_t *lr)
 {
+    if (lr->conn_id) {
+        DEQ_REMOVE_N(REF, lr->conn_id->link_route_refs, lr);
+        qdr_route_check_id_for_deletion_CT(core, lr->conn_id);
+    }
+
+    if (lr->addr) {
+        if (--lr->addr->ref_count == 0) {
+            qdr_check_addr_CT(core, lr->addr);
+        }
+    }
+
     free(lr->add_prefix);
     free(lr->del_prefix);
     free(lr->name);
@@ -420,6 +437,15 @@ void qdr_core_delete_link_route(qdr_core_t *core, 
qdr_link_route_t *lr)
 
 void qdr_core_delete_auto_link(qdr_core_t *core, qdr_auto_link_t *al)
 {
+    if (al->conn_id) {
+        DEQ_REMOVE_N(REF, al->conn_id->auto_link_refs, al);
+        qdr_route_check_id_for_deletion_CT(core, al->conn_id);
+    }
+
+    qdr_address_t *addr = al->addr;
+    if (addr && --addr->ref_count == 0)
+        qdr_check_addr_CT(core, addr);
+
     free(al->name);
     free(al->external_addr);
     qdr_core_timer_free_CT(core, al->retry_timer);
@@ -453,6 +479,17 @@ void qdr_core_remove_address(qdr_core_t *core, 
qdr_address_t *addr)
     }
 
     // Free resources associated with this address
+
+    DEQ_APPEND(addr->rlinks, addr->inlinks);
+    qdr_link_ref_t *lref = DEQ_HEAD(addr->rlinks);
+    while (lref) {
+        qdr_link_t *link = lref->link;
+        assert(link->owning_addr == addr);
+        link->owning_addr = 0;
+        qdr_del_link_ref(&addr->rlinks, link, QDR_LINK_LIST_CLASS_ADDRESS);
+        lref = DEQ_HEAD(addr->rlinks);
+    }
+
     qd_bitmask_free(addr->rnodes);
     if (addr->treatment == QD_TREATMENT_ANYCAST_CLOSEST) {
         qd_bitmask_free(addr->closest_remotes);
@@ -460,6 +497,13 @@ void qdr_core_remove_address(qdr_core_t *core, 
qdr_address_t *addr)
     else if (addr->treatment == QD_TREATMENT_ANYCAST_BALANCED) {
         free(addr->outstanding_deliveries);
     }
+
+    qdr_connection_ref_t *cr = DEQ_HEAD(addr->conns);
+    while (cr) {
+        qdr_del_connection_ref(&addr->conns, cr->conn);
+        cr = DEQ_HEAD(addr->conns);
+    }
+
     free(addr->add_prefix);
     free(addr->del_prefix);
     free_qdr_address_t(addr);


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

Reply via email to