From e45f91f350d9e9b5b04f1e0214406e852497aa4d Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 29 Oct 2025 20:42:45 +0200 Subject: [PATCH] sched/signal/sig_dispatch.c: Remove DEBUGASSERT(!sched_idletask()) The DEBUGASSERT is wrong in two cases; 1) In SIM, which does sim_timer_update from the idle task, and the sim timer runs on signals 2) If signal is dispatched from within an interrupt In these cases, if there are not available items for pending signals, return the nxsig_tcbdispatch with -EAGAIN instead of asserting. Signed-off-by: Jukka Laitinen --- sched/signal/sig_dispatch.c | 76 +++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index f65adac2bb6..e1cd559f49a 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -357,61 +357,76 @@ static FAR sigpendq_t *nxsig_add_pendingsignal(FAR struct tcb_s *stcb, * ****************************************************************************/ -static irqstate_t nxsig_alloc_dyn_pending(irqstate_t flags) +static int nxsig_alloc_dyn_pending(FAR irqstate_t *flags) { - if (!up_interrupt_context()) + int ret = OK; + bool alloc_signal = sq_empty(&g_sigpendingsignal); + bool alloc_sigact = sq_empty(&g_sigpendingaction); + + if (alloc_signal || alloc_sigact) { - bool alloc_signal = sq_empty(&g_sigpendingsignal); - bool alloc_sigact = sq_empty(&g_sigpendingaction); + FAR sigpendq_t *sigpend = NULL; + FAR sigq_t *sigq = NULL; - /* Signals are not dispatched from the idle task */ + /* We can't do memory allocations in idle task or interrupt */ - DEBUGASSERT(!sched_idletask()); - - if (alloc_signal || alloc_sigact) + if (up_interrupt_context() || sched_idletask()) { - FAR sigpendq_t *sigpend = NULL; - FAR sigq_t *sigq = NULL; + return -EAGAIN; + } - /* Leave critical section for the duration of heap operations */ + /* Leave critical section for the duration of heap operations */ - leave_critical_section(flags); + leave_critical_section(*flags); - /* Allocate more pending signals if there are no more */ + /* Allocate more pending signals if there are no more */ - if (alloc_signal) - { - sigpend = kmm_malloc(sizeof(sigpendq_t)); - } + if (alloc_signal) + { + sigpend = kmm_malloc(sizeof(sigpendq_t)); + } - /* Allocate more pending signal actions if there are no more */ + /* Allocate more pending signal actions if there are no more */ - if (alloc_sigact) - { - sigq = kmm_malloc(sizeof(sigq_t)); - } + if (alloc_sigact) + { + sigq = kmm_malloc(sizeof(sigq_t)); + } - /* Restore critical section and add the allocated structures to - * the free pending queues - */ + /* Restore critical section and add the allocated structures to + * the free pending queues + */ - flags = enter_critical_section(); + *flags = enter_critical_section(); + if (alloc_signal) + { if (sigpend) { sigpend->type = SIG_ALLOC_DYN; sq_addfirst((sq_entry_t *)sigpend, &g_sigpendingsignal); } + else + { + ret = -EAGAIN; + } + } + if (alloc_sigact) + { if (sigq) { sigq->type = SIG_ALLOC_DYN; sq_addfirst((sq_entry_t *)sigq, &g_sigpendingaction); } + else + { + ret = -EAGAIN; + } } } - return flags; + return ret; } /**************************************************************************** @@ -485,7 +500,12 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info, * needs to be done here before using the task state or sigprocmask. */ - flags = nxsig_alloc_dyn_pending(flags); + ret = nxsig_alloc_dyn_pending(&flags); + if (ret < 0) + { + leave_critical_section(flags); + return ret; + } masked = nxsig_ismember(&stcb->sigprocmask, info->si_signo);