diff options
-rw-r--r-- | include/openbsc/signal.h | 11 | ||||
-rw-r--r-- | src/chan_alloc.c | 4 | ||||
-rw-r--r-- | src/gsm_04_08.c | 25 |
3 files changed, 39 insertions, 1 deletions
diff --git a/include/openbsc/signal.h b/include/openbsc/signal.h index c2cf46a26..4a583f689 100644 --- a/include/openbsc/signal.h +++ b/include/openbsc/signal.h @@ -37,6 +37,7 @@ enum signal_subsystems { SS_SMS, SS_ABISIP, SS_NM, + SS_LCHAN, }; /* SS_PAGING signals */ @@ -55,6 +56,16 @@ enum signal_nm { S_NM_FAIL_REP, /* GSM 12.21 failure event report */ }; +/* SS_LCHAN signals */ +enum signal_lchan { + /* + * The lchan got freed with an use_count != 0 and error + * recovery needs to be carried out from within the + * signal handler. + */ + S_LCHAN_UNEXPECTED_RELEASE, +}; + typedef int signal_cbfn(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data); diff --git a/src/chan_alloc.c b/src/chan_alloc.c index fa07273fa..77a4f57bc 100644 --- a/src/chan_alloc.c +++ b/src/chan_alloc.c @@ -31,6 +31,7 @@ #include <openbsc/abis_nm.h> #include <openbsc/abis_rsl.h> #include <openbsc/debug.h> +#include <openbsc/signal.h> static void auto_release_channel(void *_lchan); @@ -193,8 +194,9 @@ void lchan_free(struct gsm_lchan *lchan) lchan->subscr = 0; } - /* We might kill an active channel... FIXME: call cancellations */ + /* We might kill an active channel... */ if (lchan->use_count != 0) { + dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); lchan->use_count = 0; } diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c index aebbd67bd..7e448dd68 100644 --- a/src/gsm_04_08.c +++ b/src/gsm_04_08.c @@ -182,6 +182,31 @@ static void allocate_loc_updating_req(struct gsm_lchan *lchan) memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation)); } +static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE) + return 0; + + /* + * Cancel any outstanding location updating request + * operation taking place on the lchan. + */ + struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data; + release_loc_updating_req(lchan); + + return 0; +} + +/* + * This will be ran by the linker when loading the DSO. We use it to + * do system initialization, e.g. registration of signal handlers. + */ +static __attribute__((constructor)) void on_dso_load_0408(void) +{ + register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL); +} + static void to_bcd(u_int8_t *bcd, u_int16_t val) { bcd[2] = val % 10; |