Bug #11395
closedruby gets stuck when entropy_avail is 0
Description
When /proc/sys/kernel/random/entropy_avail
is 0, Ruby gets stuck during initialization.
$ ruby -v
(stuck)
This is caused by r51182. I think that the GRND_NONBLOCK
flag should be set to getrandom
syscall.
The following patch works for me. But I have no idea to remove the magic number "1 (= GRND_NONBLOCK
)".
diff --git a/random.c b/random.c
index 6452456..9ef89f9 100644
--- a/random.c
+++ b/random.c
@@ -523,11 +523,14 @@ fill_random_bytes_syscall(void *seed, size_t size)
if (try_syscall) {
long ret;
errno = 0;
- ret = syscall(SYS_getrandom, seed, size, 0);
+ ret = syscall(SYS_getrandom, seed, size, 1);
if (errno == ENOSYS) {
try_syscall = 0;
return -1;
}
+ if (errno == EAGAIN) {
+ return -1;
+ }
if ((size_t)ret == size) return 0;
}
return -1;
--
Yusuke Endoh mame@ruby-lang.org
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
- Description updated (diff)
including <linux/random.h>
?
And checking errno
with EAGAIN
doesn't seem necessary since the return value should not equal to size
.
diff --git i/random.c w/random.c
index 6452456..bea5f85 100644
--- i/random.c
+++ w/random.c
@@ -516,6 +516,8 @@ fill_random_bytes_syscall(void *seed, size_t size)
return 0;
}
#elif defined __linux__ && defined SYS_getrandom
+#include <linux/random.h>
+
static int
fill_random_bytes_syscall(void *seed, size_t size)
{
@@ -523,7 +525,7 @@ fill_random_bytes_syscall(void *seed, size_t size)
if (try_syscall) {
long ret;
errno = 0;
- ret = syscall(SYS_getrandom, seed, size, 0);
+ ret = syscall(SYS_getrandom, seed, size, GRND_NONBLOCK);
if (errno == ENOSYS) {
try_syscall = 0;
return -1;
Updated by mame (Yusuke Endoh) over 9 years ago
Well, my system has SYS_getrandom
but not GRND_NONBLOCK
even in linux/random.h
.
I'm using musl libc. It might be a fault of the library.
--
Yusuke Endoh <mame@ruby-lang.org.
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
Does this header exist?
Updated by mame (Yusuke Endoh) over 9 years ago
Nobuyoshi Nakada wrote:
Does this header exist?
Yes.
compiling random.c
random.c: In function 'fill_random_bytes_syscall':
random.c:528:43: error: 'GRND_NONBLOCK' undeclared (first use in this function)
ret = syscall(SYS_getrandom, seed, size, GRND_NONBLOCK);
^
random.c:528:43: note: each undeclared identifier is reported only once for each function it appears in
Makefile:369: recipe for target 'random.o' failed
make: *** [random.o] Error 1
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
- Status changed from Assigned to Closed
Applied in changeset r51374.
random.c: get rid of blocking
- random.c (fill_random_bytes_syscall): get rid of blocking when
no entropy is available. based on the patch by mame in
[ruby-core:70114]. [Bug #11395]
Updated by mame (Yusuke Endoh) over 9 years ago
Sorry, r51374 may lead to a problem under the following situation.
- the system uses a new libc that knows
SYS_getrandom
, but - the system uses an old linux kernel that does not know
getrandom
syscall.
I guess it is not a good idea to determine the availability of getrandom
by checking if SYS_getrandom
is defined or not.
Instead, it should check the runtime kernel version or something, though it is too ugly.
I bet that we should not use the direct syscall
but wait for libc to provide a wrapper function to getrandom.
--
Yusuke Endoh mame@ruby-lang.org
Updated by mame (Yusuke Endoh) over 9 years ago
Will syscall
return ENOSYS
if the given syscall number is not available?
If so, I guess the current patch will work well.
--
Yusuke Endoh mame@ruby-lang.org
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
ENOSYS
should be for that purpose.
$ ./x86_64-linux/bin/ruby -v -e 'syscall(9999)'
ruby 2.3.0dev (2015-07-26 trunk 51386) [x86_64-linux]
-e:1: warning: We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.
-e:1:in `syscall': Function not implemented (Errno::ENOSYS)
from -e:1:in `<main>'