Skip to content

Commit 6a89481

Browse files
nirsvstinner
authored andcommitted
bpo-32186: Release the GIL during lseek and fstat (#4652)
In _io_FileIO_readall_impl(), lseek() and _Py_fstat_noraise() were called without releasing the GIL. This can cause all threads to hang for unlimited time when calling FileIO.read() and the NFS server is not accessible.
1 parent c319eee commit 6a89481

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
io.FileIO.readall() and io.FileIO.read() now release the GIL when
2+
getting the file size. Fixed hang of all threads with inaccessible NFS
3+
server. Patch by Nir Soffer.

Modules/_io/fileio.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,19 +683,23 @@ _io_FileIO_readall_impl(fileio *self)
683683
Py_ssize_t bytes_read = 0;
684684
Py_ssize_t n;
685685
size_t bufsize;
686+
int fstat_result;
686687

687688
if (self->fd < 0)
688689
return err_closed();
689690

691+
Py_BEGIN_ALLOW_THREADS
690692
_Py_BEGIN_SUPPRESS_IPH
691693
#ifdef MS_WINDOWS
692694
pos = _lseeki64(self->fd, 0L, SEEK_CUR);
693695
#else
694696
pos = lseek(self->fd, 0L, SEEK_CUR);
695697
#endif
696698
_Py_END_SUPPRESS_IPH
699+
fstat_result = _Py_fstat_noraise(self->fd, &status);
700+
Py_END_ALLOW_THREADS
697701

698-
if (_Py_fstat_noraise(self->fd, &status) == 0)
702+
if (fstat_result == 0)
699703
end = status.st_size;
700704
else
701705
end = (Py_off_t)-1;

0 commit comments

Comments
 (0)