Bug #13753
Segfault when calling `Random::DEFAULT.rand` in forked child
Description
Hi,
The following causes a segfault on 2.3.4, 2.4.1 and current (ruby 2.5.0dev (2017-07-18 trunk 59362) [x86_64-linux]
)
puts "before fork: #{Random::DEFAULT.rand(42)}"
fork do
puts "child: #{Random::DEFAULT.rand(42)}"
end
/home/owen/fork_random.rb:4: [BUG] Segmentation fault at 0x0000000000000000 ruby 2.5.0dev (2017-07-18 trunk 59362) [x86_64-linux] -- Control frame information ----------------------------------------------- c:0005 p:---- s:0020 e:000019 CFUNC :rand c:0004 p:0021 s:0015 e:000012 BLOCK /home/owen/fork_random.rb:4 [FINISH] c:0003 p:---- s:0010 e:000009 CFUNC :fork c:0002 p:0033 s:0006 e:000005 EVAL /home/owen/fork_random.rb:3 [FINISH] c:0001 p:0000 s:0003 E:000790 (none) [FINISH] -- Ruby level backtrace information ---------------------------------------- /home/owen/fork_random.rb:3:in `<main>' /home/owen/fork_random.rb:3:in `fork' /home/owen/fork_random.rb:4:in `block in <main>' /home/owen/fork_random.rb:4:in `rand' -- Machine register context ------------------------------------------------ RIP: 0x00007f99e9e7eefd RBP: 0x00007fff14180190 RSP: 0x00007fff14180178 RAX: 0x0000000000000000 RBX: 0x00007f99ea17b039 RCX: 0x0000000000000004 RDX: 0x00007f99ea2af228 RDI: 0x00007f99ea2af228 RSI: 0x0000000000000029 R8: 0x0000000000000000 R9: 0x00007f99eb0b5630 R10: 0x0000000022220021 R11: 0x00007f99ea17b060 R12: 0x00007f99e9dd96a0 R13: 0x00007fff14182df0 R14: 0x00007f99eb3d3248 R15: 0x00007f99ea27af50 EFL: 0x0000000000010202 -- C level backtrace information ------------------------------------------- /home/owen/code/ruby/ruby(rb_print_backtrace+0x19) [0x7f99e9f4e081] vm_dump.c:671 /home/owen/code/ruby/ruby(rb_vm_bugreport+0xb3) [0x7f99e9f4e4fd] vm_dump.c:941 /home/owen/code/ruby/ruby(rb_bug_context+0x117) [0x7f99e9fc098e] error.c:534 /home/owen/code/ruby/ruby(sigsegv+0x60) [0x7f99e9ec8793] signal.c:930 /lib/x86_64-linux-gnu/libpthread.so.0 [0x7f99e9983330] /home/owen/code/ruby/ruby(genrand_int32+0x57) [0x7f99e9e7eefd] random.c:189 /home/owen/code/ruby/ruby(limited_rand+0xb6) [0x7f99e9e7fda1] random.c:839 /home/owen/code/ruby/ruby(random_ulong_limited+0x142) [0x7f99e9e80483] random.c:1019 /home/owen/code/ruby/ruby(rand_int+0x74) [0x7f99e9e80a09] random.c:1149 /home/owen/code/ruby/ruby(rand_random+0xe3) [0x7f99e9e811a2] random.c:1337 /home/owen/code/ruby/ruby(random_rand+0x34) [0x7f99e9e810a2] random.c:1320 /home/owen/code/ruby/ruby(call_cfunc_m1+0x2f) [0x7f99e9f2f3dd] vm_insnhelper.c:1706 /home/owen/code/ruby/ruby(vm_call_cfunc_with_frame+0x19a) [0x7f99e9f2ff10] vm_insnhelper.c:1889
The problem is in the rb_reset_random_seed
call that happens after forking a Thread. This function call places the struct mt
inside default_rand
in a partially-uninitialised state and the next call to rand_int
(which assumes the struct mt
is initialised) tries to dereference a null pointer.
N.B. the first call to Random::DEFAULT.rand
is required to exhibit the bug else the Random instance is not placed into an inconsistent state upon forking (in particular mt->left == 1
so the next rand call correctly re-initialises the instance)
Files
Updated by owst (Owen Stephens) over 3 years ago
- File 0001-Re-initialise-Random-DEFAULT-after-forking-Bug-13753.patch 0001-Re-initialise-Random-DEFAULT-after-forking-Bug-13753.patch added
The attached patch fixes the issue by re-initialising the random instance such that calls to Random::DEFAULT.rand
after forking will succeed.
This now gives the same after-fork behaviour as Random.rand
. Incidentally, there is a comment on Random.rand
saying:
* Alias of Random::DEFAULT.rand.
which is now true in the sense that they behave the same.
Updated by nobu (Nobuyoshi Nakada) over 3 years ago
- Status changed from Open to Closed
Applied in changeset trunk|r59368.
random.c: ensure initialized
- random.c (get_rnd, try_get_rnd): ensure initialized to get rid of crash in forked processes. [ruby-core:82100] [Bug #13753]
Updated by nobu (Nobuyoshi Nakada) over 3 years ago
- Backport changed from 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN to 2.2: REQUIRED, 2.3: REQUIRED, 2.4: REQUIRED
Updated by nagachika (Tomoyuki Chikanaga) over 3 years ago
- Backport changed from 2.2: REQUIRED, 2.3: REQUIRED, 2.4: REQUIRED to 2.2: REQUIRED, 2.3: REQUIRED, 2.4: DONE
ruby_2_4 r59517 merged revision(s) 59368.
Updated by usa (Usaku NAKAMURA) over 3 years ago
- Backport changed from 2.2: REQUIRED, 2.3: REQUIRED, 2.4: DONE to 2.2: REQUIRED, 2.3: DONE, 2.4: DONE
ruby_2_3 r59546 merged revision(s) 59368.