diff options
Diffstat (limited to 'Python')
| -rw-r--r-- | Python/pythonrun.c | 1 | ||||
| -rw-r--r-- | Python/random.c | 55 | 
2 files changed, 43 insertions, 13 deletions
diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 375bf34c82..cbd62aa056 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -625,6 +625,7 @@ Py_Finalize(void)      PyDict_Fini();      PySlice_Fini();      _PyGC_Fini(); +    _PyRandom_Fini();      /* Cleanup Unicode implementation */      _PyUnicode_Fini(); diff --git a/Python/random.c b/Python/random.c index 8cf2fef7c6..1d470c703c 100644 --- a/Python/random.c +++ b/Python/random.c @@ -90,6 +90,7 @@ vms_urandom(unsigned char *buffer, Py_ssize_t size, int raise)  #if !defined(MS_WINDOWS) && !defined(__VMS) +static int urandom_fd = -1;  /* Read size bytes from /dev/urandom into buffer.     Call Py_FatalError() on error. */ @@ -133,18 +134,30 @@ dev_urandom_python(char *buffer, Py_ssize_t size)      if (size <= 0)          return 0; -    Py_BEGIN_ALLOW_THREADS -    fd = _Py_open("/dev/urandom", O_RDONLY); -    Py_END_ALLOW_THREADS -    if (fd < 0) -    { -        if (errno == ENOENT || errno == ENXIO || -            errno == ENODEV || errno == EACCES) -            PyErr_SetString(PyExc_NotImplementedError, -                            "/dev/urandom (or equivalent) not found"); +    if (urandom_fd >= 0) +        fd = urandom_fd; +    else { +        Py_BEGIN_ALLOW_THREADS +        fd = _Py_open("/dev/urandom", O_RDONLY); +        Py_END_ALLOW_THREADS +        if (fd < 0) +        { +            if (errno == ENOENT || errno == ENXIO || +                errno == ENODEV || errno == EACCES) +                PyErr_SetString(PyExc_NotImplementedError, +                                "/dev/urandom (or equivalent) not found"); +            else +                PyErr_SetFromErrno(PyExc_OSError); +            return -1; +        } +        if (urandom_fd >= 0) { +            /* urandom_fd was initialized by another thread while we were +               not holding the GIL, keep it. */ +            close(fd); +            fd = urandom_fd; +        }          else -            PyErr_SetFromErrno(PyExc_OSError); -        return -1; +            urandom_fd = fd;      }      Py_BEGIN_ALLOW_THREADS @@ -168,12 +181,20 @@ dev_urandom_python(char *buffer, Py_ssize_t size)              PyErr_Format(PyExc_RuntimeError,                           "Failed to read %zi bytes from /dev/urandom",                           size); -        close(fd);          return -1;      } -    close(fd);      return 0;  } + +static void +dev_urandom_close(void) +{ +    if (urandom_fd >= 0) { +        close(urandom_fd); +        urandom_fd = -1; +    } +} +  #endif /* !defined(MS_WINDOWS) && !defined(__VMS) */  /* Fill buffer with pseudo-random bytes generated by a linear congruent @@ -271,3 +292,11 @@ _PyRandom_Init(void)  #endif      }  } + +void +_PyRandom_Fini(void) +{ +#if !defined(MS_WINDOWS) && !defined(__VMS) +    dev_urandom_close(); +#endif +}  | 
