[PATCH] ho: Make sure the timer is always stopped

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

Holger Hans Peter Freyther holger at freyther.de
Wed Dec 17 20:24:04 UTC 2014


From: Holger Hans Peter Freyther <holger at moiji-mobile.com>

In case of a ho_chan_activ_nack (sent due another bug inside
both sysmobts and openbsc) the code would not stop the timer
but free the datastructure. This can lead to a clear segfault
when the timer has expired. Create a "free" function which is
responsible to detach the handover structure, stop the timer
(which is idempotent) and free the structure.
---
 openbsc/src/libbsc/handover_logic.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/openbsc/src/libbsc/handover_logic.c b/openbsc/src/libbsc/handover_logic.c
index 22f9883..9284f7e 100644
--- a/openbsc/src/libbsc/handover_logic.c
+++ b/openbsc/src/libbsc/handover_logic.c
@@ -54,6 +54,13 @@ struct bsc_handover {
 
 static LLIST_HEAD(bsc_handovers);
 
+static void handover_free(struct bsc_handover *ho)
+{
+	osmo_timer_del(&ho->T3103);
+	llist_del(&ho->list);
+	talloc_free(ho);
+}
+
 static struct bsc_handover *bsc_ho_by_new_lchan(struct gsm_lchan *new_lchan)
 {
 	struct bsc_handover *ho;
@@ -169,9 +176,7 @@ void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan)
 	if (free_lchan)
 		lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
 
-	osmo_timer_del(&ho->T3103);
-	llist_del(&ho->list);
-	talloc_free(ho);
+	handover_free(ho);
 }
 
 /* T3103 expired: Handover has failed without HO COMPLETE or HO FAIL */
@@ -186,8 +191,7 @@ static void ho_T3103_cb(void *_ho)
 	ho->new_lchan->conn->ho_lchan = NULL;
 	ho->new_lchan->conn = NULL;
 	lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
-	llist_del(&ho->list);
-	talloc_free(ho);
+	handover_free(ho);
 }
 
 /* RSL has acknowledged activation of the new lchan */
@@ -234,8 +238,7 @@ static int ho_chan_activ_nack(struct gsm_lchan *new_lchan)
 
 	new_lchan->conn->ho_lchan = NULL;
 	new_lchan->conn = NULL;
-	llist_del(&ho->list);
-	talloc_free(ho);
+	handover_free(ho);
 
 	/* FIXME: maybe we should try to allocate a new LCHAN here? */
 
@@ -282,9 +285,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
 	rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE);
 	lchan_release(ho->old_lchan, 0, RSL_REL_LOCAL_END);
 
-	llist_del(&ho->list);
-	talloc_free(ho);
-
+	handover_free(ho);
 	return 0;
 }
 
@@ -293,6 +294,7 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
 {
 	struct gsm_network *net = old_lchan->ts->trx->bts->network;
 	struct bsc_handover *ho;
+	struct gsm_lchan *new_lchan;
 
 	ho = bsc_ho_by_old_lchan(old_lchan);
 	if (!ho) {
@@ -302,15 +304,15 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
 
 	osmo_counter_inc(net->stats.handover.failed);
 
-	osmo_timer_del(&ho->T3103);
-	llist_del(&ho->list);
+	new_lchan = ho->new_lchan;
 
 	/* release the channel and forget about it */
 	ho->new_lchan->conn->ho_lchan = NULL;
 	ho->new_lchan->conn = NULL;
-	lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
+	handover_free(ho);
+
+	lchan_release(new_lchan, 0, RSL_REL_LOCAL_END);
 
-	talloc_free(ho);
 
 	return 0;
 }
-- 
2.1.3




More information about the OpenBSC mailing list