Commit 174b16a3d1 for freeswitch.com
commit 174b16a3d1285712f2f965f0572fd1b973f9ff41
Author: Ahron Greenberg (agree) <37550360+greenbea@users.noreply.github.com>
Date: Fri Jun 12 10:53:40 2026 -0400
[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.
diff --git a/src/mod/event_handlers/mod_amqp/mod_amqp_command.c b/src/mod/event_handlers/mod_amqp/mod_amqp_command.c
index 48cdf55ce4..ee879d2474 100644
--- a/src/mod/event_handlers/mod_amqp/mod_amqp_command.c
+++ b/src/mod/event_handlers/mod_amqp/mod_amqp_command.c
@@ -259,7 +259,8 @@ static void mod_amqp_command_response(mod_amqp_command_profile_t *profile, char
switch_safe_free(json_output);
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",
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);
queueName.bytes = NULL;
- mod_amqp_connection_close(profile->conn_active);
- profile->conn_active = NULL;
+ if (profile->conn_active) {
+ mod_amqp_connection_close(profile->conn_active);
+ profile->conn_active = NULL;
+ }
if (profile->running) {
/* We'll reconnect, but sleep to avoid hammering resources */
diff --git a/src/mod/event_handlers/mod_amqp/mod_amqp_connection.c b/src/mod/event_handlers/mod_amqp/mod_amqp_connection.c
index 758eac241e..d3b7efc767 100644
--- a/src/mod/event_handlers/mod_amqp/mod_amqp_connection.c
+++ b/src/mod/event_handlers/mod_amqp/mod_amqp_connection.c
@@ -40,9 +40,15 @@
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;
+ if (!connection) {
+ return;
+ }
+
+ old_state = connection->state;
+
connection->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");
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);
}
}
diff --git a/src/mod/event_handlers/mod_amqp/mod_amqp_logging.c b/src/mod/event_handlers/mod_amqp/mod_amqp_logging.c
index 01d08960fa..eec17581a6 100644
--- a/src/mod/event_handlers/mod_amqp/mod_amqp_logging.c
+++ b/src/mod/event_handlers/mod_amqp/mod_amqp_logging.c
@@ -296,7 +296,8 @@ switch_status_t mod_amqp_logging_send(mod_amqp_logging_profile_t *profile, mod_a
amqp_cstring_bytes(msg->pjson));
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",
profile->name, profile->conn_active->name, errstr);
diff --git a/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c b/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c
index 303927285e..259906c007 100644
--- a/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c
+++ b/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c
@@ -426,7 +426,8 @@ switch_status_t mod_amqp_producer_send(mod_amqp_producer_profile_t *profile, mod
amqp_cstring_bytes(msg->pjson));
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",
profile->name, profile->conn_active->name, errstr);