Docopt can cause a process to block when used before random pool is initialized
Closed this issue · 8 comments
Docopt can cause a process to block if the /dev/urandom pool has not yet been initialized.
Background
On more recent kernels (>3.17), the getrandom syscall has been introduced. This syscall is used by OsRng when getting a random number. The current syscall args cause it to block until the /dev/urandom pool has been initialized. The default implementation of HashMap uses RandomState for its default hasher. RandomState uses the rand crate which blocks until the /dev/urandom pool has been initialized.
System Setup
Ubuntu 15.10
Rust 1.7.0
GDB Backtrace
Catchpoint 1 (call to syscall 318), syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
38 ../sysdeps/unix/sysv/linux/x86_64/syscall.S: No such file or directory.
(gdb) bt
#0 syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
#1 0x00005555558190f5 in rand::StdRng::new::h7f6f37b37bd8a656XMy ()
#2 0x0000555555819446 in rand::thread_rng::THREAD_RNG_KEY::__init::hee923a4dca76e52cqQy ()
#3 0x0000555555801fee in rand::thread_rng::hf965b6c3dc392e76dQy ()
#4 0x0000555555629888 in docopt::collections::hash::map::RandomState::new () at ../src/libstd/collections/hash/map.rs:1638
#5 0x0000555555629864 in docopt::collections::hash::map::RandomState.Default::default () at ../src/libstd/collections/hash/map.rs:1656
#6 0x000055555562ee6f in docopt::collections::hash::map::HashMap<K, V, S>.Default::default () at ../src/libstd/collections/hash/map.rs:1261
#7 0x000055555562ee44 in docopt::collections::hash::map::HashMap<K, V, RandomState>::new () at ../src/libstd/collections/hash/map.rs:512
#8 0x000055555562edef in docopt::synonym::SynonymMap<K, V>::new () at /root/.cargo/registry/src/github.com-88ac128001ac3a9a/docopt-0.6.78/src/synonym.rs:17
#9 0x000055555562e704 in docopt::parse::Parser::new (doc=...) at /root/.cargo/registry/src/github.com-88ac128001ac3a9a/docopt-0.6.78/src/parse.rs:78
#10 0x00005555555cb238 in myprog::dopt::Docopt::new<&str> (usage=...) at /root/.cargo/registry/src/github.com-88ac128001ac3a9a/docopt-0.6.78/src/dopt.rs:177
#11 0x00005555555c7dc2 in myprog::main () at src/main.rs:101
#12 0x0000555555818505 in sys_common::unwind::try::try_fn::h9896872240422604242 ()
#13 0x00005555558157a9 in __rust_try ()
#14 0x0000555555818191 in rt::lang_start::h0d9dcd8707a91319Uoy ()
#15 0x00005555555f518a in main () at ../src/libcollections/string.rs:1734
This may be solved by using a hasher that does not rely on the random pool being initialized.
I feel like "don't ever use the default HashMap" probably isn't a good fix for this. :-/ There are oodles of things that use a HashMap, so I can't imagine that Docopt will be the only problem.
It looks like there was chatter about changing the default hasher for HashMap in rust-lang/rust#27242 and rust-lang/rust#27713. While I agree with you that its not just Docopt that will have this issue this is a concrete example where it causes problems. On some embedded Linux boards that I've got I have had to stop using Docopt for programs that are kicked off by init scripts because it takes about 2 minutes to initialize the random pool and as a result Docopt blocks those programs from starting up for 2 minutes.
You also wouldn't be able to use regex
(which uses hash maps internally).
Right. I was going to open an issue there as well.
I suspect the more appropriate place to file an issue is on rust-lang/rust
itself, since this is specifically a problem with the default HashMap
implementation.
This can be closed since rust-lang/rust#33086 landed.
@cardoe Thanks! :)