diff options
| author | Nils Maier <maierman@web.de> | 2015-02-06 17:33:22 +0100 |
|---|---|---|
| committer | Nils Maier <maierman@web.de> | 2015-02-07 17:18:45 +0100 |
| commit | ba0e32abaecedf3939905bd316336f313b3dd745 (patch) | |
| tree | 16df1163a667b23a7c2f5211b6d7a3324db2d614 /src/getrandom_linux.c | |
| parent | 9cbbe9f1bbb6d05b46fbf54b5c26cec62888ea79 (diff) | |
Handle linux getrandom returning EINTR on interrupts/signals
Also handle ENOTSUP failures where aria2 was build with linux headers
newer than the actual running kernel.
Fixes GH-336
Diffstat (limited to 'src/getrandom_linux.c')
| -rw-r--r-- | src/getrandom_linux.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/getrandom_linux.c b/src/getrandom_linux.c index 85314fd6..cbf4c32a 100644 --- a/src/getrandom_linux.c +++ b/src/getrandom_linux.c @@ -37,14 +37,42 @@ #include <unistd.h> #include <sys/syscall.h> #include <linux/random.h> +#include <errno.h> +#include <linux/errno.h> +#include <stdint.h> +#include <stdio.h> #include "config.h" #include "getrandom_linux.h" int getrandom_linux(void *buf, size_t buflen) { + int rv = 0; + uint8_t* p = buf; + while (buflen) { + int read; #ifdef HAVE_GETRANDOM - return getrandom(buf, buflen, 0); + read = getrandom(p, buflen, 0); #else // HAVE_GETRANDOM - return syscall(SYS_getrandom, buf, buflen, 0); + read = syscall(SYS_getrandom, p, buflen, 0); + /* Some libc impl. might mess this up */ + if (read == -EINTR || read == -ERESTART) { + errno = EINTR; + read = -1; + } + if (read < -1) { + errno = -read; + read = -1; + } #endif // HAVE_GETRANDOM + if (read < 0) { + if (errno == EINTR) { + continue; + } + return -1; + } + p += read; + rv += read; + buflen -= read; + } + return rv; } |
