From 1a06ea43560d8b63c45e6deddb92601324f4b46e Mon Sep 17 00:00:00 2001 From: Petro Karashchenko Date: Sun, 13 Nov 2022 00:50:02 +0200 Subject: [PATCH] sched/signal: fix error handling in sigtimedwait() Signed-off-by: Petro Karashchenko --- sched/signal/sig_timedwait.c | 56 ++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index c32e2a120ad..d8c7ffe2763 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -280,10 +280,6 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, } #endif - /* Save the set of pending signals to wait for */ - - rtcb->sigwaitmask = *set; - /* Check if we should wait for the timeout */ if (timeout != NULL) @@ -309,28 +305,44 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, waitticks = MSEC2TICK(waitmsec); #endif - /* Start the watchdog */ + if (waitticks > 0) + { + /* Save the set of pending signals to wait for */ - wd_start(&rtcb->waitdog, waitticks, - nxsig_timeout, (uintptr_t)rtcb); + rtcb->sigwaitmask = *set; - /* Now wait for either the signal or the watchdog, but - * first, make sure this is not the idle task, - * descheduling that isn't going to end well. - */ + /* Start the watchdog */ - DEBUGASSERT(!is_idle_task(rtcb)); - up_block_task(rtcb, TSTATE_WAIT_SIG); + wd_start(&rtcb->waitdog, waitticks, + nxsig_timeout, (uintptr_t)rtcb); - /* We no longer need the watchdog */ + /* Now wait for either the signal or the watchdog, but + * first, make sure this is not the idle task, + * descheduling that isn't going to end well. + */ - wd_cancel(&rtcb->waitdog); + DEBUGASSERT(!is_idle_task(rtcb)); + up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* We no longer need the watchdog */ + + wd_cancel(&rtcb->waitdog); + } + else + { + leave_critical_section(flags); + return -EAGAIN; + } } /* No timeout, just wait */ else { + /* Save the set of pending signals to wait for */ + + rtcb->sigwaitmask = *set; + /* And wait until one of the unblocked signals is posted, * but first make sure this is not the idle task, * descheduling that isn't going to end well. @@ -356,6 +368,13 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, if (nxsig_ismember(set, rtcb->sigunbinfo.si_signo)) { + /* Return the signal info to the caller if so requested */ + + if (info != NULL) + { + memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo)); + } + /* Yes.. the return value is the number of the signal that * awakened us. */ @@ -395,13 +414,6 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, } } - /* Return the signal info to the caller if so requested */ - - if (info) - { - memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo)); - } - leave_critical_section(flags); }