8000 [3.6] bpo-33021: Release the GIL during fstat() calls (GH-6019) (GH-6… · python/cpython@f3e6ead · GitHub
[go: up one dir, main page]

Skip to content

Commit f3e6ead

Browse files
miss-islingtonnirs
authored andcommitted
[3.6] bpo-33021: Release the GIL during fstat() calls (GH-6019) (GH-6160)
fstat may block for long time if the file descriptor is on a non-responsive NFS server, hanging all threads. Most fstat() calls are handled by _Py_fstat(), releasing the GIL internally, but but _Py_fstat_noraise() does not release the GIL, and most calls release the GIL explicitly around it. This patch fixes last 2 calls to _Py_fstat_no_raise(), avoiding hangs when calling: - mmap.mmap() - os.urandom() - random.seed() (cherry picked from commit 4484f9d) Co-authored-by: Nir Soffer <nirsof@gmail.com>
1 parent 424f3da commit f3e6ead

File tree

3 files changed

+17
-3
lines changed

3 files changed

+17
-3
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff 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.

Modules/mmapmodule.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
< 8000 code class="diff-text-cell hunk">
@@ -1078,6 +1078,7 @@ static PyObject *
10781078
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
10791079
{
10801080
struct _Py_stat_struct status;
1081+
int fstat_result = -1;
10811082
mmap_object *m_obj;
10821083
Py_ssize_t map_size;
10831084
off_t offset = 0;
@@ -1143,8 +1144,14 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
11431144
if (fd != -1)
11441145
(void)fcntl(fd, F_FULLFSYNC);
11451146
#endif
1146-
if (fd != -1 && _Py_fstat_noraise(fd, &status) == 0
1147-
&& S_ISREG(status.st_mode)) {
1147+
1148+
if (fd != -1) {
1149+
Py_BEGIN_ALLOW_THREADS
1150+
fstat_result = _Py_fstat_noraise(fd, &status);
1151+
Py_END_ALLOW_THREADS
1152+
}
1153+
1154+
if (fd != -1 && fstat_result == 0 && S_ISREG(status.st_mode)) {
11481155
if (map_size == 0) {
11491156
if (status.st_size == 0) {
11501157
PyErr_SetString(PyExc_ValueError,

Python/random.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,15 @@ dev_urandom(char *buffer, Py_ssize_t size, int raise)
301301

302302
if (raise) {
303303
struct _Py_stat_struct st;
304+
int fstat_result;
304305

305306
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+
306311
/* 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
308313
|| st.st_dev != urandom_cache.st_dev
309314
|| st.st_ino != urandom_cache.st_ino) {
310315
/* Something changed: forget the cached fd (but don't close it,

0 commit comments

Comments
 (0)
0