--- /dev/null
+Creating io.FileIO() and builtin file() objects now release the GIL when
+checking the file descriptor. io.FileIO.readall(), io.FileIO.read(), and
+file.read() now release the GIL when getting the file size. Fixed hang of all
+threads with inaccessible NFS server. Patch by Nir Soffer.
{
#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
struct stat buf;
+ int res;
if (self->fd < 0)
return 0;
- if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fstat(self->fd, &buf);
+ Py_END_ALLOW_THREADS
+
+ if (res == 0 && S_ISDIR(buf.st_mode)) {
errno = EISDIR;
PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
return -1;
{
#if defined(HAVE_FSTAT)
struct stat buf;
- if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
- PyObject *exc;
- char *msg = strerror(EBADF);
- exc = PyObject_CallFunction(PyExc_OSError, "(is)",
- EBADF, msg);
- PyErr_SetObject(PyExc_OSError, exc);
- Py_XDECREF(exc);
- return -1;
+ int res;
+ PyObject *exc;
+ char *msg;
+
+ if (!_PyVerify_fd(fd)) {
+ goto badfd;
}
-#endif
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fstat(fd, &buf);
+ Py_END_ALLOW_THREADS
+
+ if (res < 0 && errno == EBADF) {
+ goto badfd;
+ }
+
return 0;
+
+badfd:
+ msg = strerror(EBADF);
+ exc = PyObject_CallFunction(PyExc_OSError, "(is)",
+ EBADF, msg);
+ PyErr_SetObject(PyExc_OSError, exc);
+ Py_XDECREF(exc);
+ return -1;
+#else
+ return 0;
+#endif
}
#ifdef HAVE_FSTAT
off_t pos, end;
struct stat st;
- if (fstat(self->fd, &st) == 0) {
+ int res;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fstat(self->fd, &st);
+ Py_END_ALLOW_THREADS
+
+ if (res == 0) {
end = st.st_size;
+
+ Py_BEGIN_ALLOW_THREADS
pos = lseek(self->fd, 0L, SEEK_CUR);
+ Py_END_ALLOW_THREADS
+
/* Files claiming a size smaller than SMALLCHUNK may
actually be streaming pseudo-files. In this case, we
apply the more aggressive algorithm below.
{
#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);
#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
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);
}