diff options
author | Nir Soffer <nirsof@gmail.com> | 2017-12-07 20:25:39 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2017-12-07 20:25:39 (GMT) |
commit | 830daae1c82ed33deef0086b7b6323e5be0b0cc8 (patch) | |
tree | 0c11e6b6281ec736bbae427c7100e7d8af65b63f /Objects/fileobject.c | |
parent | 12fa6b1e2ff8112b0a9f61949c3d5252a75bf909 (diff) | |
download | cpython-830daae1c82ed33deef0086b7b6323e5be0b0cc8.zip cpython-830daae1c82ed33deef0086b7b6323e5be0b0cc8.tar.gz cpython-830daae1c82ed33deef0086b7b6323e5be0b0cc8.tar.bz2 |
[2.7] bpo-32186: Release the GIL during fstat and lseek calls (#4651)
In fileio, there were 3 fstat() calls and one lseek() call that did not
release the GIL during the call. This can cause all threads to hang for
unlimited time when using io.FileIO with inaccessible NFS server.
Same issue seen in fileio exists also in fileobject, fixed in the same
way.
Diffstat (limited to 'Objects/fileobject.c')
-rw-r--r-- | Objects/fileobject.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 2f63c37..8d1c581 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -121,10 +121,15 @@ dircheck(PyFileObject* f) { #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) struct stat buf; + int res; if (f->f_fp == NULL) return f; - if (fstat(fileno(f->f_fp), &buf) == 0 && - S_ISDIR(buf.st_mode)) { + + Py_BEGIN_ALLOW_THREADS + res = fstat(fileno(f->f_fp), &buf); + Py_END_ALLOW_THREADS + + if (res == 0 && S_ISDIR(buf.st_mode)) { char *msg = strerror(EISDIR); PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)", EISDIR, msg, f->f_name); @@ -1010,7 +1015,13 @@ new_buffersize(PyFileObject *f, size_t currentsize) #ifdef HAVE_FSTAT off_t pos, end; struct stat st; - if (fstat(fileno(f->f_fp), &st) == 0) { + int res; + + Py_BEGIN_ALLOW_THREADS + res = fstat(fileno(f->f_fp), &st); + Py_END_ALLOW_THREADS + + if (res == 0) { end = st.st_size; /* The following is not a bug: we really need to call lseek() *and* ftell(). The reason is that some stdio libraries @@ -1021,7 +1032,11 @@ new_buffersize(PyFileObject *f, size_t currentsize) works. We can't use the lseek() value either, because we need to take the amount of buffered data into account. (Yet another reason why stdio stinks. :-) */ + + Py_BEGIN_ALLOW_THREADS pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR); + Py_END_ALLOW_THREADS + if (pos >= 0) { pos = ftell(f->f_fp); } |