12 Commits
Author SHA1 Message Date
Samuel Williams 84a8652f01 coroutine: consistently return the context that resumed transfer. (#18814) 2026-09-14 03:04:04 +00:00
Koichi SasadaandClaude Opus 5 8c7c80f4da coroutine: do not write to the target after switching away
coroutine_transfer() restores target->from after the switch, that is,
after this coroutine is resumed -- by then it may have been resumed by
someone else and target may be freed.

With M:N threads it usually is: a Ruby thread parks by transferring to
its shared native thread's context (thread_sched_wait_running_turn), and
that thread, finding the ready queue empty, retires and frees nt and
nt->nt_context.  Over 40 retires in the reproducer below, the number of
threads still parked on the retiring context was a median of 19 (max 61,
zero in four cases); each writes to it when it is next resumed.
sizeof(ucontext_t) is 968, so the write lands in a freed 1008-byte
region, and once that is reused it corrupts the new owner:

  free(): invalid next size (fast)
    ruby_xfree_sized ... st_free_entries -> rb_st_free_table
    ractor_free_all_ports -> ractor_notify_exit -> ractor_atexit
    thread_start_func_2 -> co_start -> coroutine_trampoline

  AddressSanitizer: heap-use-after-free
    WRITE of size 8 in coroutine_transfer (Context.h:97), thread T3
    968 bytes inside a 1008-byte region freed in nt_start ->
    native_thread_destroy_self, allocated in native_thread_alloc

from is read only by the trampoline, when target starts, so the restore
is dead by the time the switch returns.  Skip it under
COROUTINE_TARGET_MAY_BE_FREED, which thread_pthread.c defines; cont.c
and other embedders keep the original behaviour.  Only ucontext runs
M:N threads today, but the lifetime rule is not specific to them, so
guard every backend that has the restore.

Fibers never hit this: a suspended fiber still references its target, so
it cannot be collected.  A native thread's context is not a Ruby object
and is freed by hand.

Reproducer: clang-20 -O1 --enable-shared --with-coroutine=ucontext,
bootstraptest/test_ractor.rb (the case at line 2603 spawns 2000 Ractors)
four times in parallel on four CPUs: 21 of 48 runs died before, 0 of 48
after.  Under ASAN, the isolated case eight at a time: 120 of 120
reported before, 0 of 120 after.

CI: https://github.com/ruby/ruby/actions/runs/31942932752/job/95154613098

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 04:57:21 +09:00
Samuel Williams 42130a64f0 Replace copy coroutine with pthread implementation. 2021-07-01 11:23:03 +12:00
Benoit Dalozeandxtkoba 229cbeba8c Fix -Wundef warnings in coroutine/*/Context.h
* See [Feature #17752]

Co-authored-by: xtkoba (Tee KOBAYASHI) <xtkoba+ruby@gmail.com>
2021-05-04 14:56:55 +02:00
Nobuyoshi Nakada f1c36f2e6b Added include guards to coroutine headers 2021-01-22 23:21:25 +09:00
卜部昌平 ce4ea956d2 function pointers are not void*
The same as 8427fca49b.
2020-02-06 11:46:51 +09:00
Samuel Williams bf04fe086b Remove "All Rights Reserved." from Copyright statement. 2019-12-28 12:45:37 +13:00
Samuel Williams f96216df8d Remove "All Rights Reserved." from Copyright statement. 2019-12-28 12:41:47 +13:00
Yusuke Endoh f4d9daf2b6 coroutine/ucontext/Context.c: define __EXTENSIONS__ explicitly
instead of ruby/config.h, per samuel's request.

https://github.com/ruby/ruby/commit/dbfd4b780e3914a3f27e92c2248254452bf0fd6b#diff-7fd78c3cc8a19b7e0637502983ec26ff
2019-12-05 22:24:58 +09:00
Yusuke Endoh dbfd4b780e coroutine/ucontext/Context.c: Include "ruby/config.h" for Solaris
getcontext, makecontext, and swapcontext seem to be available only when
`__EXTENSION__` is defined on Solaris.
2019-12-04 20:59:39 +09:00
Samuel Williams 001f187ed6 Make fiber_pool more conservative on platforms with limited address space.
We use COROUTINE_LIMITED_ADDRESS_SPACE to select platforms where address
space is 32-bits or less. Fiber pool implementation enables more book
keeping, and reduces upper limits, in order to minimise address space
utilisation.
2019-07-18 20:54:55 +12:00
Samuel Williams 6c6bf9ffcb Add ucontext coroutine implementation for generic fallback. 2019-06-26 20:19:53 +12:00