bpo-33021: Release the GIL during fstat() calls (GH-6019) · python/cpython@4484f9d (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 +Release the GIL during fstat() calls, avoiding hang of all threads when
2 +calling mmap.mmap(), os.urandom(), and random.seed(). Patch by Nir Soffer.
Original file line number Diff line number Diff line change
@@ -1050,6 +1050,7 @@ static PyObject *
1050 1050 new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
1051 1051 {
1052 1052 struct _Py_stat_struct status;
1053 +int fstat_result;
1053 1054 mmap_object *m_obj;
1054 1055 Py_ssize_t map_size;
1055 1056 off_t offset = 0;
@@ -1115,8 +1116,14 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
1115 1116 if (fd != -1)
1116 1117 (void)fcntl(fd, F_FULLFSYNC);
1117 1118 #endif
1118 -if (fd != -1 && _Py_fstat_noraise(fd, &status) == 0
1119 -&& S_ISREG(status.st_mode)) {
1119 +
1120 +if (fd != -1) {
1121 +Py_BEGIN_ALLOW_THREADS
1122 +fstat_result = _Py_fstat_noraise(fd, &status);
1123 +Py_END_ALLOW_THREADS
1124 + }
1125 +
1126 +if (fd != -1 && fstat_result == 0 && S_ISREG(status.st_mode)) {
1120 1127 if (map_size == 0) {
1121 1128 if (status.st_size == 0) {
1122 1129 PyErr_SetString(PyExc_ValueError,
Original file line number Diff line number Diff line change
@@ -301,10 +301,15 @@ dev_urandom(char *buffer, Py_ssize_t size, int raise)
301 301
302 302 if (raise) {
303 303 struct _Py_stat_struct st;
304 +int fstat_result;
304 305
305 306 if (urandom_cache.fd >= 0) {
307 +Py_BEGIN_ALLOW_THREADS
308 +fstat_result = _Py_fstat_noraise(urandom_cache.fd, &st);
309 +Py_END_ALLOW_THREADS
310 +
306 311 /* Does the fd point to the same thing as before? (issue #21207) */
307 -if (_Py_fstat_noraise(urandom_cache.fd, &st)
312 +if (fstat_result
308 313 |
309 314 |
310 315 /* Something changed: forget the cached fd (but don't close it,