Skip to content

Commit fd8a721

Browse files
committed
Merge pull request #1594 from pguyot/w07/fix-timeout-bug
Fix a concurrency issue yielding a timeout bug Ensure that `scheduler_make_ready` and `scheduler_set_timeout` calls `sys_signal`. As `global->waiting_scheduler` was cached or read without holding `global->schedulers_mutex`, in some cases `sys_signal` was not called yielding a timeout bug where a message is in the queue but the process is not awaken. These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 1c9f4e2 + 16bab9c commit fd8a721

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

src/libAtomVM/scheduler.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -305,18 +305,16 @@ static void scheduler_make_ready(Context *ctx)
305305
}
306306
list_remove(&ctx->processes_list_head);
307307
#ifndef AVM_NO_SMP
308-
bool waiting_scheduler = global->waiting_scheduler;
309-
if (!waiting_scheduler) {
308+
if (SMP_MUTEX_TRYLOCK(global->schedulers_mutex)) {
310309
// Start a new scheduler if none are going to take this process.
311-
if (SMP_MUTEX_TRYLOCK(global->schedulers_mutex)) {
312-
if (global->running_schedulers > 0
313-
&& global->running_schedulers < global->online_schedulers
314-
&& !context_get_flags(ctx, Running)) {
315-
global->running_schedulers++;
316-
smp_scheduler_start(global);
317-
}
318-
SMP_MUTEX_UNLOCK(global->schedulers_mutex);
310+
if (!global->waiting_scheduler
311+
&& global->running_schedulers > 0
312+
&& global->running_schedulers < global->online_schedulers
313+
&& !context_get_flags(ctx, Running)) {
314+
global->running_schedulers++;
315+
smp_scheduler_start(global);
319316
}
317+
SMP_MUTEX_UNLOCK(global->schedulers_mutex);
320318
}
321319
#endif
322320
// Move to ready queue (from waiting or running)
@@ -326,7 +324,12 @@ static void scheduler_make_ready(Context *ctx)
326324
list_append(&global->ready_processes, &ctx->processes_list_head);
327325
SMP_SPINLOCK_UNLOCK(&global->processes_spinlock);
328326
#ifndef AVM_NO_SMP
329-
if (waiting_scheduler) {
327+
if (SMP_MUTEX_TRYLOCK(global->schedulers_mutex)) {
328+
if (global->waiting_scheduler) {
329+
sys_signal(global);
330+
}
331+
SMP_MUTEX_UNLOCK(global->schedulers_mutex);
332+
} else {
330333
sys_signal(global);
331334
}
332335
#elif defined(AVM_TASK_DRIVER_ENABLED)
@@ -410,7 +413,12 @@ void scheduler_set_timeout(Context *ctx, avm_int64_t timeout)
410413
SMP_SPINLOCK_UNLOCK(&glb->timer_spinlock);
411414

412415
#ifndef AVM_NO_SMP
413-
if (glb->waiting_scheduler) {
416+
if (SMP_MUTEX_TRYLOCK(glb->schedulers_mutex)) {
417+
if (glb->waiting_scheduler) {
418+
sys_signal(glb);
419+
}
420+
SMP_MUTEX_UNLOCK(glb->schedulers_mutex);
421+
} else {
414422
sys_signal(glb);
415423
}
416424
#elif defined(AVM_TASK_DRIVER_ENABLED)

0 commit comments

Comments
 (0)