diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2013-08-30 22:26:02 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2013-08-30 22:26:02 (GMT) |
commit | 4879a963d4a2020f4c26f2583f3ac35ec8d6edfe (patch) | |
tree | 88453f566e2dfc3c6908db58335742262330b92a | |
parent | 267964c837bb7a1c60a7ce3cb8963a7cced7abb1 (diff) | |
download | cpython-4879a963d4a2020f4c26f2583f3ac35ec8d6edfe.zip cpython-4879a963d4a2020f4c26f2583f3ac35ec8d6edfe.tar.gz cpython-4879a963d4a2020f4c26f2583f3ac35ec8d6edfe.tar.bz2 |
Issue #18756: os.urandom() now uses a lazily-opened persistent file descriptor, so as to avoid using many file descriptors when run in parallel from multiple threads.
-rw-r--r-- | Include/pythonrun.h | 1 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Python/pythonrun.c | 1 | ||||
-rw-r--r-- | Python/random.c | 55 |
4 files changed, 48 insertions, 13 deletions
diff --git a/Include/pythonrun.h b/Include/pythonrun.h index aca5915..8fdb5b5 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -246,6 +246,7 @@ PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); PyAPI_FUNC(void) _PyGC_Fini(void); PyAPI_FUNC(void) PySlice_Fini(void); PyAPI_FUNC(void) _PyType_Fini(void); +PyAPI_FUNC(void) _PyRandom_Fini(void); PyAPI_DATA(PyThreadState *) _Py_Finalizing; #endif @@ -51,6 +51,10 @@ Core and Builtins Library ------- +- Issue #18756: os.urandom() now uses a lazily-opened persistent file + descriptor, so as to avoid using many file descriptors when run in + parallel from multiple threads. + - Issue #18418: After fork(), reinit all threads states, not only active ones. Patch by A. Jesse Jiryu Davis. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 375bf34..cbd62aa 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 8cf2fef..1d470c7 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 +} |