DISPATCH-1549: properly free terminus on transactional link rejection
diff --git a/src/router_core/connections.c b/src/router_core/connections.c
index 1a44baf..b7284a4 100644
--- a/src/router_core/connections.c
+++ b/src/router_core/connections.c
@@ -573,6 +573,8 @@
set_safe_ptr_qdr_connection_t(link->conn, &action->args.connection.conn);
set_safe_ptr_qdr_link_t(link, &action->args.connection.link);
+
+ // ownership of source/target passed to core, core must free them when done
action->args.connection.source = source;
action->args.connection.target = target;
qdr_action_enqueue(link->core, action);
@@ -1647,12 +1649,15 @@
{
qdr_link_t *link = safe_deref_qdr_link_t(action->args.connection.link);
qdr_connection_t *conn = safe_deref_qdr_connection_t(action->args.connection.conn);
- if (discard || !link || !conn)
- return;
-
qdr_terminus_t *source = action->args.connection.source;
qdr_terminus_t *target = action->args.connection.target;
+ if (discard || !link || !conn) {
+ qdr_terminus_free(source);
+ qdr_terminus_free(target);
+ return;
+ }
+
link->oper_status = QDR_LINK_OPER_UP;
link->attach_count++;
diff --git a/src/router_core/modules/address_lookup_client/lookup_client.c b/src/router_core/modules/address_lookup_client/lookup_client.c
index aa6f968..ea4c888 100644
--- a/src/router_core/modules/address_lookup_client/lookup_client.c
+++ b/src/router_core/modules/address_lookup_client/lookup_client.c
@@ -326,8 +326,8 @@
qdr_address_t *addr,
qdr_link_t *link,
qd_direction_t dir,
- qdr_terminus_t *source,
- qdr_terminus_t *target,
+ qdr_terminus_t *source, // must free when done
+ qdr_terminus_t *target, // must free when done
bool link_route,
bool unavailable,
bool core_endpoint,
@@ -337,27 +337,20 @@
if (core_endpoint) {
qdrc_endpoint_do_bound_attach_CT(core, addr, link, source, target);
+ source = target = 0; // ownership passed to qdrc_endpoint_do_bound_attach_CT
}
else if (unavailable && qdr_terminus_is_coordinator(dir == QD_INCOMING ? target : source) && !addr) {
qdr_link_outbound_detach_CT(core, link, 0, QDR_CONDITION_COORDINATOR_PRECONDITION_FAILED, true);
- qdr_terminus_free(source);
- qdr_terminus_free(target);
}
else if (unavailable) {
qdr_link_outbound_detach_CT(core, link, qdr_error(QD_AMQP_COND_NOT_FOUND, "Node not found"), 0, true);
- qdr_terminus_free(source);
- qdr_terminus_free(target);
}
-
else if (!addr) {
//
// No route to this destination, reject the link
//
qdr_link_outbound_detach_CT(core, link, 0, QDR_CONDITION_NO_ROUTE_TO_DESTINATION, true);
- qdr_terminus_free(source);
- qdr_terminus_free(target);
}
-
else if (link_route) {
//
// This is a link-routed destination, forward the attach to the next hop
@@ -365,21 +358,18 @@
qdr_terminus_t *term = dir == QD_INCOMING ? target : source;
if (qdr_terminus_survives_disconnect(term) && !core->qd->allow_resumable_link_route) {
qdr_link_outbound_detach_CT(core, link, 0, QDR_CONDITION_INVALID_LINK_EXPIRATION, true);
- qdr_terminus_free(source);
- qdr_terminus_free(target);
} else {
if (conn->role != QDR_ROLE_INTER_ROUTER && conn->connection_info) {
link->disambiguated_name = disambiguated_link_name(conn->connection_info, link->name);
}
bool success = qdr_forward_attach_CT(core, addr, link, source, target);
- if (!success) {
+ if (success) {
+ source = target = 0; // ownership passed to qdr_forward_attach_CT
+ } else {
qdr_link_outbound_detach_CT(core, link, 0, QDR_CONDITION_NO_ROUTE_TO_DESTINATION, true);
- qdr_terminus_free(source);
- qdr_terminus_free(target);
}
}
}
-
else if (dir == QD_INCOMING && qdr_terminus_is_coordinator(target)) {
//
// This target terminus is a coordinator.
@@ -389,6 +379,7 @@
// The attach response should have a null target to indicate refusal and the immediately coming detach.
//
qdr_link_outbound_second_attach_CT(core, link, source, 0);
+ source = 0; // ownership passed to qdr_link_outbound_second_attach_CT
//
// Now, send back a detach with the error amqp:precondition-failed
@@ -401,6 +392,7 @@
//
qdr_core_bind_address_link_CT(core, addr, link);
qdr_link_outbound_second_attach_CT(core, link, source, target);
+ source = target = 0; // ownership passed to qdr_link_outbound_second_attach_CT
//
// Issue the initial credit only if one of the following
@@ -427,6 +419,11 @@
if (link->conn->role == QDR_ROLE_EDGE_CONNECTION)
qdrc_event_link_raise(core, QDRC_EVENT_LINK_EDGE_DATA_ATTACHED, link);
}
+
+ if (source)
+ qdr_terminus_free(source);
+ if (target)
+ qdr_terminus_free(target);
}
diff --git a/tests/lsan.supp b/tests/lsan.supp
index a37c399..765aef8 100644
--- a/tests/lsan.supp
+++ b/tests/lsan.supp
@@ -35,7 +35,6 @@
leak:qdr_route_add_link_route_CT
leak:qdr_route_connection_opened_CT
leak:qdr_subscribe_CT
-leak:qdr_terminus
leak:router_annotate_message
leak:qd_container_register_node_type