mirror of
https://github.com/open5gs/open5gs.git
synced 2026-04-28 03:19:31 +00:00
[NFM] Prevent dispatch of SBI events to NF instance FSMs finalized by SIGTERM (#3938)
In state_operational, guard against dispatching to NF instance FSMs whose state has been reset to zero by ogs_fsm_fini() in event_termination(). Drop any incoming SBI events for those instances and log an error, preventing assertion failures when late HTTP callbacks arrive after an asynchronous SIGTERM shutdown.
This commit is contained in:
parent
db0196cba7
commit
53e9e059ed
10 changed files with 259 additions and 31 deletions
|
|
@ -332,10 +332,33 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &sbi_message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &sbi_message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -215,10 +215,33 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -234,10 +234,33 @@ void bsf_state_operational(ogs_fsm_t *s, bsf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -205,10 +205,33 @@ void nssf_state_operational(ogs_fsm_t *s, nssf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -381,10 +381,33 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -167,10 +167,33 @@ void scp_state_operational(ogs_fsm_t *s, scp_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -241,11 +241,32 @@ void sepp_state_operational(ogs_fsm_t *s, sepp_event_t *e)
|
|||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
old_state = OGS_FSM_STATE(&nf_instance->sm);
|
||||
ogs_assert(old_state);
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
if (old_state) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
/*
|
||||
* The SEPP on the H-PLMN should send a n32c-handshake message
|
||||
|
|
|
|||
|
|
@ -711,10 +711,33 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &sbi_message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &sbi_message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -288,10 +288,33 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
|
|
@ -225,10 +225,33 @@ void udr_state_operational(ogs_fsm_t *s, udr_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->h.sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
/*
|
||||
* Guard against dispatching to an FSM that may have been finalized
|
||||
* by an asynchronous shutdown triggered by SIGTERM.
|
||||
*
|
||||
* In init.c’s event_termination(), which can be invoked asynchronously
|
||||
* when the process receives SIGTERM, we iterate over all NF instances:
|
||||
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
* ogs_sbi_nf_fsm_fini(nf_instance);
|
||||
* and call ogs_fsm_fini() on each instance’s FSM. That finalizes the FSM
|
||||
* and its state is reset to zero.
|
||||
*
|
||||
* After event_termination(), any incoming SBI response—such as an NRF
|
||||
* client callback arriving after deregistration—would otherwise be
|
||||
* dispatched into a dead FSM and trigger an assertion failure.
|
||||
*
|
||||
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
|
||||
* - If non-zero, the FSM is still active and can safely handle the event.
|
||||
* - If zero, the FSM has already been finalized by event_termination(),
|
||||
* so we log and drop the event to allow graceful shutdown.
|
||||
*/
|
||||
if (OGS_FSM_STATE(&nf_instance->sm)) {
|
||||
e->h.sbi.message = &message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
} else
|
||||
ogs_error("NF instance FSM has been finalized");
|
||||
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue