From b1ef1fae5ede96b245589b891f2ff0cbec0abb02 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 28 Nov 2023 17:22:25 +0200 Subject: [PATCH 1/2] gh-90102: Optimize io.FileIO.isatty() Only invoke the isatty() system call for character devices and cache the result. --- ...3-11-28-17-22-03.gh-issue-90102.JrgowE.rst | 2 ++ Modules/_io/fileio.c | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-11-28-17-22-03.gh-issue-90102.JrgowE.rst diff --git a/Misc/NEWS.d/next/Library/2023-11-28-17-22-03.gh-issue-90102.JrgowE.rst b/Misc/NEWS.d/next/Library/2023-11-28-17-22-03.gh-issue-90102.JrgowE.rst new file mode 100644 index 00000000000000..9fcad18240ba45 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-28-17-22-03.gh-issue-90102.JrgowE.rst @@ -0,0 +1,2 @@ +Optimize :meth:`io.FileIO.isatty`. Only invoke the ``isatty()`` system call +for character devices and cache the result. It also makes :func:`open` a bit faster. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 8a73ea0365b7a3..cd86cfcdfe77d1 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -69,6 +69,7 @@ typedef struct { unsigned int writable : 1; unsigned int appending : 1; signed int seekable : 2; /* -1 means unknown */ + int isatty : 2; /* -1 means unknown */ unsigned int closefd : 1; char finalizing; unsigned int blksize; @@ -195,6 +196,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->writable = 0; self->appending = 0; self->seekable = -1; + self->isatty = -1; self->blksize = 0; self->closefd = 1; self->weakreflist = NULL; @@ -475,6 +477,11 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, if (fdfstat.st_blksize > 1) self->blksize = fdfstat.st_blksize; #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ +#ifdef S_ISCHR + if (!S_ISCHR(fdfstat.st_mode)) { + self->isatty = 0; + } +#endif /* S_ISCHR */ } #if defined(MS_WINDOWS) || defined(__CYGWIN__) @@ -1141,16 +1148,16 @@ static PyObject * _io_FileIO_isatty_impl(fileio *self) /*[clinic end generated code: output=932c39924e9a8070 input=cd94ca1f5e95e843]*/ { - long res; - if (self->fd < 0) return err_closed(); - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = isatty(self->fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - return PyBool_FromLong(res); + if (self->isatty < 0) { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + self->isatty = isatty(self->fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } + return PyBool_FromLong(self->isatty); } #include "clinic/fileio.c.h" From fae5fc5cd40be013733742561942f52a039a1385 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 28 Nov 2023 20:24:17 +0200 Subject: [PATCH 2/2] Fix a race condition. --- Modules/_io/fileio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index cd86cfcdfe77d1..f3cec9750cd844 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1151,11 +1151,13 @@ _io_FileIO_isatty_impl(fileio *self) if (self->fd < 0) return err_closed(); if (self->isatty < 0) { + int res; Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH - self->isatty = isatty(self->fd); + res = isatty(self->fd); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS + self->isatty = res; } return PyBool_FromLong(self->isatty); }