1123 Commits
Author SHA1 Message Date
John Hawthorn 28f2eae4cf Flush the current Ractor's stdout/stderr before spawning
prefork() flushed rb_stdout and rb_stderr, which are the main Ractor's IOs.
From another Ractor that takes the write_lock of an IO the Ractor does not
own. When a main Ractor thread holds it (any thread logging to $stdout will
do), the spawning Ractor's only thread sleeps on the mutex and
rb_check_deadlock, which only looks at the Ractor's own threads, raises
"No live threads left. Deadlock?" (fatal) from Kernel#spawn/system/popen.

Use rb_ractor_stdout()/rb_ractor_stderr() so each Ractor flushes its own.

[Bug #22434]
2026-10-20 01:18:41 -07:00
Douglas Eichelberger e06b9da3f2 Reset the fork lock in the child without unlocking it
A thread that is waiting for the fork lock when another thread forks
exists only in the parent, but on macOS the child's copy of the lock
still counts it. After the child unlocks its copy,
pthread_rwlock_destroy() and pthread_rwlock_init() fail with EBUSY, so
the child aborts with
"[BUG] pthread_rwlock_destroy: Resource busy (EBUSY)". Lookup threads
wait for the lock whenever a fork holds it, so a process that resolves
names in background threads while it forks loses a child now and then.

Reset the child's copy by assigning PTHREAD_RWLOCK_INITIALIZER, as
rb_internal_thread_event_hooks_rw_lock_atfork() does for its lock, and
do not unlock it first. With a waiter counted, macOS's unlock enters the
kernel to wake it, and the state that leaves behind for the lock's
address survives the assignment, so a later waiter in the child can
sleep forever although no thread holds the lock. FreeBSD already skipped
the unlock in the child (dc8c382266), and on glibc the child's unlock
does not release the write lock anyway.

[Bug #22445]
2026-10-15 20:23:08 +02:00
Douglas Eichelberger 44f7c6b00d Join getaddrinfo and getnameinfo threads before fork
A getaddrinfo thread calls getaddrinfo(3) inside rb_thread_prevent_fork,
but on glibc its thread exit takes the resolver configuration lock again
after the thread has released the fork lock. A fork that lands then
leaves the child with that lock held, and every later name lookup in the
child blocks forever. getnameinfo(3) attaches the same resolver state,
even for a name in /etc/hosts, and its thread ran outside
rb_thread_prevent_fork altogether.

Make the lookup threads joinable and have fork join any that may still
be exiting. As a lookup thread finishes, still inside
rb_thread_prevent_fork, it swaps itself into a single slot with an
atomic exchange and joins the thread it displaced, which has usually
exited by then, and rb_thread_acquire_fork_lock joins whatever is left
in the slot. Once lookups settle, at most one finished thread is left
unjoined. The slot holds pthread_t as a pointer, with NULL for empty,
which assumes pthread_t is scalar and never 0.

getnameinfo threads now run within rb_thread_prevent_fork and register
as they exit, as getaddrinfo threads do, and where getnameinfo runs
without a helper thread it is called within rb_thread_prevent_fork too.
So fork also waits for a reverse lookup in progress, as it already did
for a forward one. raddrinfo_pthread_create now always creates joinable
threads, which drops its pthread_detach fallback for platforms without
pthread_attr_setdetachstate.

The slot is kept across fork, so every fork path that keeps running
Ruby code has to take the fork lock. On the BSDs, Process.daemon forks
with daemon(3) and did not take it, so the daemon would inherit the
registered thread, and its next fork would abort in pthread_join with
ESRCH. Take and release the fork lock around daemon(3) as rb_fork_ruby
does. daemon(3) can fail in the child as well as in the parent, so
compare pids to tell which process returned.

[Bug #22406]
2026-10-14 10:46:00 +02:00
Hiroshi SHIBATAandClaude Opus 5.5 ee3d6c987b Use rb_len_t for the lengths and indices left in long
These still held String and Array lengths and indices in long, or cast them to long. rb_len_t is still long everywhere, so the generated code does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:45:25 +09:00
Hiroshi SHIBATAandClaude Opus 5 803c68f0da Use rb_len_t for lengths in process.c and signal.c
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-09 14:00:15 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 612e44ed48 Remove non-Windows spawnv helpers in process.c
USE_SPAWNV needs spawnv without a working fork, which only Windows has since OS/2 support was removed. The non-Windows proc_spawn_cmd_internal and proc_spawn_sh were never compiled, and the Windows proc_spawn_cmd_internal macro was unused because proc_spawn_cmd calls rb_w32_uaspawn_flags directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:21:14 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 d4bb55c0c7 Drop _WIN32 conditions covered by HAVE_* macros
win32/Makefile.sub and the mingw part of configure.ac already define HAVE_FCNTL_H, HAVE_SPAWNV and HAVE_TIMES, and leave HAVE_SYS_IOCTL_H undefined.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:21:14 +09:00
Hiroshi SHIBATAandClaude Fable 5 29c206dd55 [Bug #22280] Mark $? and $$ as box-ready
They are readonly virtual variables backed by per-thread/per-process
state, but user boxes cached the first read in the box gvar_tbl. The
cache stores a clone, and cloning Process::Status does not copy the
wrapped struct, so $? after Kernel#system or IO.popen returned an
uninitialized status, and $$ returned the parent's pid in a forked
child. Bypass the cache like $&, $', and friends.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-18 07:22:55 +09:00
Koichi SasadaandClaude Opus 5 88208f9465 [DOC] Process.clock_gettime: CLOCK_THREAD_CPUTIME_ID under M:N
The clock belongs to the native thread that reads it.  An M:N Ruby thread
moves between native threads, so two reads taken from one Ruby thread can
come from different native threads and the later one can be smaller.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 22:54:47 +09:00
John Hawthorn e1fcca5c11 Mark Process::Status as FROZEN_SHAREABLE 2026-08-21 10:17:45 -07:00
Nobuyoshi Nakada fff4e38e4a [Bug #22243] Ensure forked process to terminate
The forked process should terminate reliably even if an exception
occurs.
2026-08-13 14:11:29 +09:00
Jean Boussier 5b505f860b Reduce RHASH_TBL_RAW usage 2026-08-06 12:41:07 +02:00
Shizuo Fujita 553f19d9b2 [DOC] Fix the $? description of Process::Status.wait (#18109)
The documentation says that Process::Status.wait sets the thread-local
variable $? when there are child processes, but it never does.
rb_process_status_wait does not call rb_last_status_set, and $? is left
untouched:

    $?                        # => nil
    Process.spawn('cat /nop') # => 4996
    Process::Status.wait      # => #<Process::Status: pid 4996 exit 1>
    $?                        # => nil

The existing example showed this as well: the pid displayed for $?
(1155508) did not match the pid of the returned status (1155880),
contradicting the surrounding text.

Since $? is never set, the "does not set thread-local variable $?"
note in the no-child-process case is now redundant and has been folded
into the general description.
2026-07-30 15:24:42 +09:00
Ajay Krishnan 7521a308b0 [DOC] Fix Kernel#system exception condition 2026-07-26 11:16:45 -04:00
Jean Boussier 8645a948c0 Right size temporary dump objects
The Range Marshal compat dumper would allocate
an Object with no size information, hence get a 32B slot
with enough space for 2 ivars, then insert 3 ivars causing
it to spill.

This isn't a big problem, but somewhat shows that the interface
isn't WVA aware.

By introducing `rb_class_allocate_instance_capa` we can directly
allocate an object with enough room.
2026-07-22 23:52:01 +02:00
Hiroshi SHIBATAandClaude Fable 5 201dece9d7 Eager load the error decoration gems from Process.warmup
The decoration gems are loaded lazily on the first error display, which
in a pre-forking server happens after fork in each child. That loads
their code outside copy-on-write shared memory and busts method caches
at runtime when they prepend Exception#detailed_message.

Process.warmup, called before the first fork by such servers, now loads
them eagerly so the prepended decorators land in shared memory and the
cache invalidation happens during boot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 11:49:03 +09:00
Nobuyoshi Nakada 878d20ef1b Use bounded strings in process and cwd handling
Track explicit lengths while parsing command strings and comparing the
current directory. This avoids relying on Ruby string terminators and
makes separators in the generated argument buffer explicit.
2026-07-15 13:28:39 +09:00
Hiroshi SHIBATAandClaude Opus 4.8 4659696b19 Remove BSD/OS (BSDi) support
BSD/OS was discontinued in 2003 and the bsdi* target has been
unbuildable for decades. This also removes the BROKEN_SETREUID and
BROKEN_SETREGID fallbacks in process.c, which no other platform
ever defined.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:34:40 +09:00
Sharon Rosner b072acf0c1 Add rb_process_status_for to intern/process.h. (#15213)
[Feature #21704]
2026-07-12 12:41:23 +12:00
Daisuke Fujimura (fd0) 9e195b7a51 process.c: remove unreachable CYGWIN32 code path 2026-07-11 21:39:08 +09:00
Nobuyoshi Nakada b17078a0de Suppress unused-function warnings 2026-07-07 18:39:52 +09:00
John HawthornandLuke Gruber daffaaee73 Mark most TypedData types as THREAD_SAFE_FREE
Set RUBY_TYPED_THREAD_SAFE_FREE on TypedData types whose dfree function
is trivially safe, and only frees its own memory

Types not yet marked as THREAD_SAFE_FREE:
- id2ref_tbl_type: sets the process-global id2ref_tbl to NULL.
- mutex_data_type: unlinks itself from another thread's keeping_mutexes list.
- autoload_data_type: deletes nodes from a shared intrusive list.
- autoload_const_type: deletes itself from a shared list.
- rb_cont_data_type: mutates the shared fiber pool and the global first_jit_cont list.
- rb_fiber_data_type: delegates to cont_free.
- FiberPoolDataType: mutates shared fiber pool free-lists.
- ractor_data_type: reconfigures global VM event-hook flags and call caches.
- exported_object_registry: frees a global table under the VM lock.
- rb_box_data_type (Box::Entry): unlinks classext from other live class and module objects.
- box_ext_cleanup_type: dereferences another String object and calls unlink.
- monitor_data_type: uses the default free, so the flag has no effect.

Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
2026-06-23 13:30:26 -07:00
Jean Boussier 78495ca415 imemo_tmp_buffer: skip marking when useless
In many place ALLOC_V / ALLOCV_N is used as a safer `alloca`,
and to behave like stack memory, `ALLOCV` does scan its buffer
for references using `rb_gc_mark_locations`.

The problem is that it's quite slow, and in many cases, the
temporary buffer is known not to contain any references.

e.g. `ALLOCV_N(uint32_t, buf0, len)` can't possibly contain references,
as the element size is too small.
2026-06-16 16:52:32 +02:00
Nobuyoshi Nakada fcb4746845 Show the class in a message for non-Symbol wrong exec-options 2026-05-24 18:40:59 +09:00
Nobuyoshi Nakada 3d137cf5fd Remove duplicate GC guard
Now there is a guard also in `execarg_parent_end` since
commit:9ae6ee5a59e74e629f73222938b53a6eae8d2ded.
2026-05-23 18:01:33 +09:00
John Hawthorn c1f70394c9 Remove rb_imemo_tmpbuf_set_ptr 2026-02-24 09:39:35 -08:00
Kuba Suder bea48adbca [DOC] fixed pid shown in the doc comment on fork 2026-01-28 02:48:37 +00:00
Stan Lo 4cd6661e18 Reorganize page documentations (#15154)
Re-organize page docs
2025-11-27 20:12:24 +00:00
Nobuyoshi Nakada 45fcb9d590 Adjust indent [ci skip] 2025-11-24 17:30:47 +09:00
Peter Zhu 390220579b Replace vfork with fork for ASAN
Older versions of ASAN do not support vfork. See https://github.com/google/sanitizers/issues/925
2025-11-23 10:54:44 -08:00
Peter Zhu 2447380894 Run rb_gc_before_fork after before_exec
before_exec stops the timer thread, which requires locking the Ractor
scheduler lock. This may deadlock if rb_gc_before_fork locks the VM.
2025-11-20 14:30:42 -08:00
Ricardo Trindade 48eb907f6b [DOC] Fix formatting of seconds parameter in documentation
There's an additional colon sign in the documentation for Process.clock_gettime
2025-09-24 19:06:24 +09:00
Peter Zhu b0ce1fd549 Combine rb_imemo_tmpbuf_auto_free_pointer and rb_imemo_tmpbuf_new 2025-09-15 09:25:20 -04:00
Jean Boussier 5bcc639b34 Disallow forking from non-main ractor
[Bug #17516]

`fork(2)` only leave the calling thread alive in the child.
Because of this forking from the non-main ractor can easily
leave the VM in a corrupted state.

It may be possible in the future to carefully allow forking from non-main
Ractor, but shot term it's preferable to add this restriction.
2025-06-24 15:10:40 +01:00
Nobuyoshi Nakada edaa27ce45 Suppress warnings by gcc-13 with -Og 2025-06-05 22:33:02 +09:00
Nobuyoshi Nakada aad9fa2853 Use RB_VM_LOCKING 2025-05-25 15:22:43 +09:00
John Hawthorn d7ad53f249 Acquire VM lock around fork
Otherwise it might be held by another Ractor, causing a deadlock in the
new process.
2025-05-08 10:53:28 -07:00
Nobuyoshi Nakada 4a67ef09cc [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
Nobuyoshi Nakada e433e6515e [DOC] Exclude 'Class' and 'Module' from RDoc's autolinking 2025-01-02 12:36:06 +09:00
Nobuyoshi Nakada b4ec22fe6c [DOC] Exclude 'Method' from RDoc's autolinking 2025-01-02 12:23:49 +09:00
Nobuyoshi Nakada d441d35107 [DOC] Exclude 'Process' from RDoc's autolinking 2025-01-02 11:58:15 +09:00
Hiroshi SHIBATA 9967eccc54 Removed Process::Status#& and Process::Status#>> 2024-12-25 20:10:18 +09:00
Yusuke Endoh c07fb79150 Avoid file descriptor leak
`extra_fd` was leaked if `fd_set_cloexec` fails -- I can't think of any
chance of that happening here, but just in case.

Coverity Scan found this issue.
2024-12-18 11:10:05 +09:00
Alan Wu 0c9c6efc20 Add missing fiber nil check to avoid slow rb_check_funcall()
Check for nil like other callers of rb_fiber_scheduler_current().
2024-12-09 16:20:01 -05:00
Matt Valentine-HouseandPeter Zhu 551be8219e Place all non-default GC API behind USE_SHARED_GC
So that it doesn't get included in the generated binaries for builds
that don't support loading shared GC modules

Co-Authored-By: Peter Zhu <peter@peterzhu.ca>
2024-11-25 13:05:23 +00:00
Samuel Williams 86e8a36e77 Revert "Direct access to fptr->fd should prefer to use the internal/io.h. (#11793)"
This reverts commit 6ea0dcc978 that was accidentally merged.
2024-10-04 08:25:43 +00:00
Samuel Williams 6ea0dcc978 Direct access to fptr->fd should prefer to use the internal/io.h. (#11793) 2024-10-04 07:44:23 +00:00
Nobuyoshi Nakada dc8c382266 Fix bug at fork on FreeBSD
The main thread in a forked process appears not to own the read-write
lock.
2024-09-19 18:08:12 +09:00
Nobuyoshi Nakada c193ca5218 Adjust indent [ci skip] 2024-09-19 14:33:32 +09:00
Nobuyoshi Nakada d80a81c152 Constify struct getpwnam_r_args::login 2024-09-13 09:28:51 +09:00