diff options
author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2017-02-27 18:24:48 +0100 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2017-03-02 17:06:46 +0100 |
commit | 99bddc16848934ce809aaf7fe81376e4616cdc42 (patch) | |
tree | 6f77da5324c36fa782cace2d50a9aad5e8911c4f | |
parent | 182ad6cb396d39f8dd8547e8506969e7ae1ca877 (diff) |
fix segfault: when a conn is closed, clean up its trans
From conn_fsm timeouts, it is possible that a subscriber connection gets
discarded even though e.g. an SMS gsm_trans is still in the queue. Clean up all
pending trans when the conn is closed, to prevent segfaults.
Change-Id: I17a68c8c7e8faa44f9d19029a8f82bc7936c4d52
-rw-r--r-- | openbsc/include/openbsc/transaction.h | 1 | ||||
-rw-r--r-- | openbsc/src/libmsc/subscr_conn.c | 10 | ||||
-rw-r--r-- | openbsc/src/libmsc/transaction.c | 10 |
3 files changed, 21 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h index 468768309..07ab7a7da 100644 --- a/openbsc/include/openbsc/transaction.h +++ b/openbsc/include/openbsc/transaction.h @@ -75,5 +75,6 @@ void trans_free(struct gsm_trans *trans); int trans_assign_trans_id(struct gsm_network *net, struct vlr_subscr *vsub, uint8_t protocol, uint8_t ti_flag); int trans_has_conn(const struct gsm_subscriber_connection *conn); +void trans_conn_closed(struct gsm_subscriber_connection *conn); #endif diff --git a/openbsc/src/libmsc/subscr_conn.c b/openbsc/src/libmsc/subscr_conn.c index 80a938db1..97072d13b 100644 --- a/openbsc/src/libmsc/subscr_conn.c +++ b/openbsc/src/libmsc/subscr_conn.c @@ -197,6 +197,16 @@ static void subscr_conn_fsm_cleanup(struct osmo_fsm_inst *fi, conn->conn_fsm = NULL; + /* If we're closing in a middle of a trans, we need to clean up */ + if (conn->use_count) { + DEBUGP(DMM, "%s: still in use (%u), cleaning up transactions\n", + vlr_subscr_name(conn->vsub), conn->use_count); + trans_conn_closed(conn); + } + if (conn->use_count) + LOGP(DMM, LOGL_ERROR, "%s: closing conn but still in use (%u)\n", + vlr_subscr_name(conn->vsub), conn->use_count); + /* temporary hack, see owned_by_msc */ if (!conn->owned_by_msc) { DEBUGP(DMM, "%s leaving bsc_subscr_con_free() to bsc_api.c, owned_by_msc = false\n", diff --git a/openbsc/src/libmsc/transaction.c b/openbsc/src/libmsc/transaction.c index 7ea485b42..071acbc36 100644 --- a/openbsc/src/libmsc/transaction.c +++ b/openbsc/src/libmsc/transaction.c @@ -191,3 +191,13 @@ int trans_has_conn(const struct gsm_subscriber_connection *conn) return 0; } + +void trans_conn_closed(struct gsm_subscriber_connection *conn) +{ + struct gsm_trans *trans, *t2; + + llist_for_each_entry_safe(trans, t2, &conn->network->trans_list, entry) { + if (trans->conn == conn) + trans_free(trans); + } +} |