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

Skip to content

Commit 4484f9d

Browse files
nirspitrou
authored andcommitted
bpo-33021: Release the GIL during fstat() calls (GH-6019)
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()
1 parent e756f66 commit 4484f9d

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
@@ -1050,6 +1050,7 @@ static PyObject *
10501050
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
10511051
{
10521052
struct _Py_stat_struct status;
1053+
int fstat_result;
10531054
mmap_object *m_obj;
10541055
Py_ssize_t map_size;
10551056
off_t offset = 0;
@@ -1115,8 +1116,14 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
11151116
if (fd != -1)
11161117
(void)fcntl(fd, F_FULLFSYNC);
11171118
#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)) {
11201127
if (map_size == 0) {
11211128
if (status.st_size == 0) {
11221129
PyErr_SetString(PyExc_ValueError,

Python/bootstrap_hash.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