diff options
author | KJ Tsanaktsidis <[email protected]> | 2023-09-15 11:33:32 +1000 |
---|---|---|
committer | GitHub <[email protected]> | 2023-09-15 10:33:32 +0900 |
commit | 0117a6d389c5b607eaec1b7f917132efa356f665 (patch) | |
tree | 573381ae40e12579515be9e571aef2590f89c76f | |
parent | f08cac066e3d327f2925607d7a33c8e9738aa4ee (diff) |
Fix Thread#native_thread_id being cached across fork (#8418)
The native thread ID can and does change on some operating systems (e.g.
Linux) after forking, so it needs to be re-queried.
[Bug #19873]
Notes
Notes:
Merged-By: nurse <[email protected]>
-rw-r--r-- | test/ruby/test_thread.rb | 30 | ||||
-rw-r--r-- | thread_pthread.c | 27 |
2 files changed, 45 insertions, 12 deletions
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index 703373b11e..bcd6590903 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -3,6 +3,7 @@ require 'test/unit' require "rbconfig/sizeof" require "timeout" +require "fiddle" class TestThread < Test::Unit::TestCase class Thread < ::Thread @@ -1443,6 +1444,35 @@ q.pop assert_nil th1.native_thread_id end + def test_thread_native_thread_id_across_fork_on_linux + rtld_default = Fiddle.dlopen(nil) + omit "this test is only for Linux" unless rtld_default.sym_defined?('gettid') + + gettid = Fiddle::Function.new(rtld_default['gettid'], [], Fiddle::TYPE_INT) + + parent_thread_id = Thread.main.native_thread_id + real_parent_thread_id = gettid.call + + assert_equal real_parent_thread_id, parent_thread_id + + child_lines = nil + IO.popen('-') do |pipe| + if pipe + # parent + child_lines = pipe.read.lines + else + # child + puts Thread.main.native_thread_id + puts gettid.call + end + end + child_thread_id = child_lines[0].chomp.to_i + real_child_thread_id = child_lines[1].chomp.to_i + + assert_equal real_child_thread_id, child_thread_id + refute_equal parent_thread_id, child_thread_id + end + def test_thread_interrupt_for_killed_thread opts = { timeout: 5, timeout_error: nil } diff --git a/thread_pthread.c b/thread_pthread.c index 057c50c124..7c53325240 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -637,6 +637,18 @@ rb_thread_sched_destroy(struct rb_thread_sched *sched) clear_thread_cache_altstack(); } +#ifdef RB_THREAD_T_HAS_NATIVE_ID +static int +get_native_thread_id(void) +{ +#ifdef __linux__ + return (int)syscall(SYS_gettid); +#elif defined(__FreeBSD__) + return pthread_getthreadid_np(); +#endif +} +#endif + #if defined(HAVE_WORKING_FORK) static void thread_cache_reset(void); static void @@ -646,6 +658,9 @@ thread_sched_atfork(struct rb_thread_sched *sched) thread_cache_reset(); rb_thread_sched_init(sched); thread_sched_to_running(sched, GET_THREAD()); +#ifdef RB_THREAD_T_HAS_NATIVE_ID + GET_THREAD()->nt->tid = get_native_thread_id(); +#endif } #endif @@ -693,18 +708,6 @@ ruby_thread_set_native(rb_thread_t *th) #endif } -#ifdef RB_THREAD_T_HAS_NATIVE_ID -static int -get_native_thread_id(void) -{ -#ifdef __linux__ - return (int)syscall(SYS_gettid); -#elif defined(__FreeBSD__) - return pthread_getthreadid_np(); -#endif -} -#endif - static void native_thread_init(struct rb_native_thread *nt) { |