[mod_amqp] prevent segfault on double connection close

When a command response publish failed, `mod_amqp_command_response` closed
the connection and cleared conn_active. The command thread teardown then
called mod_amqp_connection_close(NULL), causing a segfault.

Also fix amqp_error_string2() calls to pass status codes without erroneous negation.
This commit is contained in:
Ahron Greenberg (agree)
2026-06-12 10:53:40 -04:00
committed by GitHub
parent be554e4a08
commit 174b16a3d1
4 changed files with 19 additions and 7 deletions
@@ -259,7 +259,8 @@ static void mod_amqp_command_response(mod_amqp_command_profile_t *profile, char
switch_safe_free(json_output); switch_safe_free(json_output);
if (amqp_status != AMQP_STATUS_OK) { if (amqp_status != AMQP_STATUS_OK) {
const char *errstr = amqp_error_string2(-amqp_status); const char *errstr = amqp_error_string2(amqp_status);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] failed to send event on connection[%s]: %s\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] failed to send event on connection[%s]: %s\n",
profile->name, profile->conn_active->name, errstr); profile->name, profile->conn_active->name, errstr);
@@ -498,8 +499,10 @@ void * SWITCH_THREAD_FUNC mod_amqp_command_thread(switch_thread_t *thread, void
amqp_bytes_free(queueName); amqp_bytes_free(queueName);
queueName.bytes = NULL; queueName.bytes = NULL;
mod_amqp_connection_close(profile->conn_active); if (profile->conn_active) {
profile->conn_active = NULL; mod_amqp_connection_close(profile->conn_active);
profile->conn_active = NULL;
}
if (profile->running) { if (profile->running) {
/* We'll reconnect, but sleep to avoid hammering resources */ /* We'll reconnect, but sleep to avoid hammering resources */
@@ -40,9 +40,15 @@
void mod_amqp_connection_close(mod_amqp_connection_t *connection) void mod_amqp_connection_close(mod_amqp_connection_t *connection)
{ {
amqp_connection_state_t old_state = connection->state; amqp_connection_state_t old_state;
int status = 0; int status = 0;
if (!connection) {
return;
}
old_state = connection->state;
connection->state = NULL; connection->state = NULL;
if (old_state != NULL) { if (old_state != NULL) {
@@ -50,7 +56,8 @@ void mod_amqp_connection_close(mod_amqp_connection_t *connection)
mod_amqp_log_if_amqp_error(amqp_connection_close(old_state, AMQP_REPLY_SUCCESS), "Closing connection"); mod_amqp_log_if_amqp_error(amqp_connection_close(old_state, AMQP_REPLY_SUCCESS), "Closing connection");
if ((status = amqp_destroy_connection(old_state))) { if ((status = amqp_destroy_connection(old_state))) {
const char *errstr = amqp_error_string2(-status); const char *errstr = amqp_error_string2(status);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error destroying amqp connection: %s\n", errstr); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error destroying amqp connection: %s\n", errstr);
} }
} }
@@ -296,7 +296,8 @@ switch_status_t mod_amqp_logging_send(mod_amqp_logging_profile_t *profile, mod_a
amqp_cstring_bytes(msg->pjson)); amqp_cstring_bytes(msg->pjson));
if (status < 0) { if (status < 0) {
const char *errstr = amqp_error_string2(-status); const char *errstr = amqp_error_string2(status);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] failed to send event on connection[%s]: %s\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] failed to send event on connection[%s]: %s\n",
profile->name, profile->conn_active->name, errstr); profile->name, profile->conn_active->name, errstr);
@@ -426,7 +426,8 @@ switch_status_t mod_amqp_producer_send(mod_amqp_producer_profile_t *profile, mod
amqp_cstring_bytes(msg->pjson)); amqp_cstring_bytes(msg->pjson));
if (status < 0) { if (status < 0) {
const char *errstr = amqp_error_string2(-status); const char *errstr = amqp_error_string2(status);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] failed to send event on connection[%s]: %s\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] failed to send event on connection[%s]: %s\n",
profile->name, profile->conn_active->name, errstr); profile->name, profile->conn_active->name, errstr);