aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-02-27 18:24:48 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-03-02 17:06:46 +0100
commit99bddc16848934ce809aaf7fe81376e4616cdc42 (patch)
tree6f77da5324c36fa782cace2d50a9aad5e8911c4f
parent182ad6cb396d39f8dd8547e8506969e7ae1ca877 (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.h1
-rw-r--r--openbsc/src/libmsc/subscr_conn.c10
-rw-r--r--openbsc/src/libmsc/transaction.c10
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);
+ }
+}