From 3b0445080865304705cd3082a0c76d23df637b79 Mon Sep 17 00:00:00 2001 From: ligd Date: Tue, 6 Sep 2022 16:33:58 +0800 Subject: [PATCH] sched: fix corner case wd_cancel assert crash There one ways can caused this: mq_timedreceive TIMER IRQ do wd_timer -> wd_func1 mq_send -> wd_func2 nxmq_rcvtimeout -> crash Resolve: Stop the watchdog when mq_send Signed-off-by: ligd --- sched/mqueue/mq_rcvinternal.c | 5 +++++ sched/mqueue/mq_sndinternal.c | 5 +++++ sched/signal/sig_dispatch.c | 12 ++++++++++++ 3 files changed, 22 insertions(+) diff --git a/sched/mqueue/mq_rcvinternal.c b/sched/mqueue/mq_rcvinternal.c index fab06d232a4..3dc6e48c5a7 100644 --- a/sched/mqueue/mq_rcvinternal.c +++ b/sched/mqueue/mq_rcvinternal.c @@ -298,6 +298,11 @@ ssize_t nxmq_do_receive(FAR struct mqueue_inode_s *msgq, DEBUGASSERT(btcb != NULL); + if (WDOG_ISACTIVE(&btcb->waitdog)) + { + wd_cancel(&btcb->waitdog); + } + btcb->msgwaitq = NULL; msgq->nwaitnotfull--; up_unblock_task(btcb); diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c index 45cefbf2cc8..5dc27106eaf 100644 --- a/sched/mqueue/mq_sndinternal.c +++ b/sched/mqueue/mq_sndinternal.c @@ -405,6 +405,11 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq, DEBUGASSERT(btcb); + if (WDOG_ISACTIVE(&btcb->waitdog)) + { + wd_cancel(&btcb->waitdog); + } + btcb->msgwaitq = NULL; msgq->nwaitnotempty--; up_unblock_task(btcb); diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index 7553c5d633f..aa94ab5e297 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -363,6 +363,12 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) { memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); stcb->sigwaitmask = NULL_SIGNAL_SET; + + if (WDOG_ISACTIVE(&stcb->waitdog)) + { + wd_cancel(&stcb->waitdog); + } + up_unblock_task(stcb); leave_critical_section(flags); } @@ -399,6 +405,12 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) { memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); stcb->sigwaitmask = NULL_SIGNAL_SET; + + if (WDOG_ISACTIVE(&stcb->waitdog)) + { + wd_cancel(&stcb->waitdog); + } + up_unblock_task(stcb); }