diff options
| -rw-r--r-- | thread_pthread.c | 20 | ||||
| -rw-r--r-- | version.h | 2 |
2 files changed, 21 insertions, 1 deletions
diff --git a/thread_pthread.c b/thread_pthread.c index 77994796f1..53ad08d782 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1514,6 +1514,8 @@ get_native_thread_id(void) #endif #if defined(HAVE_WORKING_FORK) +void rb_internal_thread_event_hooks_rw_lock_atfork(void); + static void thread_sched_atfork(struct rb_thread_sched *sched) { @@ -1545,6 +1547,8 @@ thread_sched_atfork(struct rb_thread_sched *sched) ccan_list_head_init(&vm->ractor.sched.timeslice_threads); ccan_list_head_init(&vm->ractor.sched.running_threads); + rb_internal_thread_event_hooks_rw_lock_atfork(); + VM_ASSERT(sched->is_running); sched->is_running_timeslice = false; @@ -3315,6 +3319,22 @@ struct rb_internal_thread_event_hook { static pthread_rwlock_t rb_internal_thread_event_hooks_rw_lock = PTHREAD_RWLOCK_INITIALIZER; +#if defined(HAVE_WORKING_FORK) +void +rb_internal_thread_event_hooks_rw_lock_atfork(void) +{ + // After fork(), this rwlock may have been held by a now-dead thread. + // + // pthread_rwlock_destroy() on a held lock is undefined behavior, and + // pthread_rwlock_init() on an already-initialized lock is also undefined + // behavior + // + // Direct assignment of PTHREAD_RWLOCK_INITIALIZER is safe and portable. + rb_internal_thread_event_hooks_rw_lock = + (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; +} +#endif + rb_internal_thread_event_hook_t * rb_internal_thread_add_event_hook(rb_internal_thread_event_callback callback, rb_event_flag_t internal_event, void *user_data) { @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 10 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 196 +#define RUBY_PATCHLEVEL 197 #include "ruby/version.h" #include "ruby/internal/abi.h" |
