From 84a5c4f674fdd39c102ce5dff4fe37d40f3aa603 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Mon, 28 Jan 2019 17:12:01 +0100 Subject: [PATCH 1/2] cpu/native: fix race condition in thread_yield_higher() Error case: 1. thread_yield_higher() stores the thread's ucontext 2. creates an "isr ucontext" for isr_thread_yield, switches to it Case 1: no signals are pending, continues in isr_thread_yield() 3a. sched_run is called 4a. return to sched_active_thread ucontext Case 2: signals pending (the crashing scenario), continues in native_irq_handler() 3b. handles signals 4b. if sched_context_switch_request is set, call sched_run 5b. return to sched_active_thread ucontext 4b misses the call to sched_run(), leading to a possible return into a non-ready thread. (cherry picked from commit 62bb4cc52695b8d9d57de8133f6cc1d62b1785c4) --- cpu/native/native_cpu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c index 2629e55df067..655562565e77 100644 --- a/cpu/native/native_cpu.c +++ b/cpu/native/native_cpu.c @@ -208,6 +208,8 @@ void isr_thread_yield(void) void thread_yield_higher(void) { + sched_context_switch_request = 1; + if (_native_in_isr == 0) { ucontext_t *ctx = (ucontext_t *)(sched_active_thread->sp); _native_in_isr = 1; @@ -224,9 +226,6 @@ void thread_yield_higher(void) } irq_enable(); } - else { - sched_context_switch_request = 1; - } } void native_cpu_init(void) From b3ede8df2f9b1a19020bd2e8abe998e121676d7c Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Mon, 28 Jan 2019 17:14:16 +0100 Subject: [PATCH 2/2] core/msg: add assert for problem identified in #10881 (cherry picked from commit 82b2362bc34686ac21f21b9b5623ea15242ee1d3) --- core/msg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/msg.c b/core/msg.c index a46875f16e8b..86ee0dd287ae 100644 --- a/core/msg.c +++ b/core/msg.c @@ -330,6 +330,7 @@ static int _msg_receive(msg_t *m, int block) thread_yield_higher(); /* sender copied message */ + assert(sched_active_thread->status != STATUS_RECEIVE_BLOCKED); } else { irq_restore(state);