mirror of
https://github.com/ruby/ruby.git
synced 2026-11-08 01:20:26 +08:00
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]