added 2 commits
February 13, 2026 13:34Old code:
```c
t = q_ready_;
/* No task ready - check if all tasks are done */
if (!t) {
/* If there are tasks waiting or suspended, idle */
if (q_waiting_ || q_suspended_) {
mrb_hal_task_idle_cpu(mrb);
continue;
```
IRQ possibly happens between `t = q_ready_;` and `if (q_waiting_ || q_suspended_) {` and, for example, a waiting task may move to the ready queue.
As a result, the infinite loop in mrb_task_run unexpectedly breaks in spite of not all the task is dormant.
This patch fixes the issue above by setting the `exitting` condition with a critical section.
The current implementation of `task_init_context` inheriting a receiver from the parent task is unstable and causes critical faults, especially on microcontrollers. - It leads to a HardFault on devices like Raspberry Pi Pico 2 by accessing a potentially NULL `mrb->c->ci`. - Even when `mrb->c->ci` is not NULL, this incomplete context copy causes other memory errors (SEGV). This patch reverts to the safer, previous behavior, that I implemented in picoruby/picoruby, of always initializing a new task's receiver to `top_self`, ensuring predictable and robust operation. The issue was likely masked on POSIX systems due to the unpredictable nature of undefined behavior.
hasumikin
changed the title
Fix mruby-task: wrapping by critical section and the
Fix mruby-task: wrapping by critical section and setting initial task receiver to top_self