From fb708e169a0ba992b3550144aa56c8937a4b6b1e Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Tue, 15 Nov 2022 11:51:07 +0100 Subject: [PATCH 1/3] GH-97001: Release GIL in termios extension --- Modules/termios.c | 88 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/Modules/termios.c b/Modules/termios.c index 354e5ca18d04d8..2c4ba6bd2b5cf2 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -82,7 +82,12 @@ termios_tcgetattr_impl(PyObject *module, int fd) { termiosmodulestate *state = PyModule_GetState(module); struct termios mode; - if (tcgetattr(fd, &mode) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcgetattr(fd, &mode); + Py_END_ALLOW_THREADS + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -169,7 +174,12 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) /* Get the old mode, in case there are any hidden fields... */ termiosmodulestate *state = PyModule_GetState(module); struct termios mode; - if (tcgetattr(fd, &mode) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcgetattr(fd, &mode); + Py_END_ALLOW_THREADS + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -211,7 +221,12 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) return PyErr_SetFromErrno(state->TermiosError); if (cfsetospeed(&mode, (speed_t) ospeed) == -1) return PyErr_SetFromErrno(state->TermiosError); - if (tcsetattr(fd, when, &mode) == -1) + + Py_BEGIN_ALLOW_THREADS + r = tcsetattr(fd, when, &mode); + Py_END_ALLOW_THREADS + + if (r == -1) return PyErr_SetFromErrno(state->TermiosError); Py_RETURN_NONE; @@ -235,7 +250,13 @@ termios_tcsendbreak_impl(PyObject *module, int fd, int duration) /*[clinic end generated code: output=5945f589b5d3ac66 input=dc2f32417691f8ed]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcsendbreak(fd, duration) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcsendbreak(fd, duration); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -256,7 +277,13 @@ termios_tcdrain_impl(PyObject *module, int fd) /*[clinic end generated code: output=5fd86944c6255955 input=c99241b140b32447]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcdrain(fd) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcdrain(fd); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -282,7 +309,13 @@ termios_tcflush_impl(PyObject *module, int fd, int queue) /*[clinic end generated code: output=2424f80312ec2f21 input=0f7d08122ddc07b5]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcflush(fd, queue) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcflush(fd, queue); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -308,7 +341,13 @@ termios_tcflow_impl(PyObject *module, int fd, int action) /*[clinic end generated code: output=afd10928e6ea66eb input=c6aff0640b6efd9c]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcflow(fd, action) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcflow(fd, action); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -333,7 +372,13 @@ termios_tcgetwinsize_impl(PyObject *module, int fd) #if defined(TIOCGWINSZ) termiosmodulestate *state = PyModule_GetState(module); struct winsize w; - if (ioctl(fd, TIOCGWINSZ, &w) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = ioctl(fd, TIOCGWINSZ, &w); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -352,7 +397,12 @@ termios_tcgetwinsize_impl(PyObject *module, int fd) #elif defined(TIOCGSIZE) termiosmodulestate *state = PyModule_GetState(module); struct ttysize s; - if (ioctl(fd, TIOCGSIZE, &s) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = ioctl(fd, TIOCGSIZE, &s); + Py_END_ALLOW_THREADS + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -433,15 +483,25 @@ termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz) return NULL; } - if (ioctl(fd, TIOCSWINSZ, &w) == -1) { + int r; + Py_BEGIN_ALLOW_THREADS + r = ioctl(fd, TIOCSWINSZ, &w); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } Py_RETURN_NONE; #elif defined(TIOCGSIZE) && defined(TIOCSSIZE) struct ttysize s; + int r; /* Get the old ttysize because it might have more fields. */ - if (ioctl(fd, TIOCGSIZE, &s) == -1) { + Py_BEGIN_ALLOW_THREADS + r = ioctl(fd, TIOCGSIZE, &s); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -453,7 +513,11 @@ termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz) return NULL; } - if (ioctl(fd, TIOCSSIZE, &s) == -1) { + Py_BEGIN_ALLOW_THREADS + r = ioctl(fd, TIOCSSIZE, &s); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } From 71165cd030cc134561838c61b9ce2da77c39bb14 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 10:55:26 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2022-11-15-10-55-24.gh-issue-97001.KeQuVF.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2022-11-15-10-55-24.gh-issue-97001.KeQuVF.rst diff --git a/Misc/NEWS.d/next/Library/2022-11-15-10-55-24.gh-issue-97001.KeQuVF.rst b/Misc/NEWS.d/next/Library/2022-11-15-10-55-24.gh-issue-97001.KeQuVF.rst new file mode 100644 index 00000000000000..014161cf7b1d44 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-11-15-10-55-24.gh-issue-97001.KeQuVF.rst @@ -0,0 +1 @@ +Release the GIL when calling termios APIs to avoid blocking threads. From 60806bdb8620c5a4747d00ac7cd363f4ceaf3bc6 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Mon, 21 Nov 2022 13:02:30 +0100 Subject: [PATCH 3/3] Dedent the code in Py_*_ALLOW_THREADS blocks This matches the rest of the code base. --- Modules/termios.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/termios.c b/Modules/termios.c index 2c4ba6bd2b5cf2..fcc8f042679870 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -85,7 +85,7 @@ termios_tcgetattr_impl(PyObject *module, int fd) int r; Py_BEGIN_ALLOW_THREADS - r = tcgetattr(fd, &mode); + r = tcgetattr(fd, &mode); Py_END_ALLOW_THREADS if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -177,7 +177,7 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) int r; Py_BEGIN_ALLOW_THREADS - r = tcgetattr(fd, &mode); + r = tcgetattr(fd, &mode); Py_END_ALLOW_THREADS if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -223,7 +223,7 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) return PyErr_SetFromErrno(state->TermiosError); Py_BEGIN_ALLOW_THREADS - r = tcsetattr(fd, when, &mode); + r = tcsetattr(fd, when, &mode); Py_END_ALLOW_THREADS if (r == -1) @@ -253,7 +253,7 @@ termios_tcsendbreak_impl(PyObject *module, int fd, int duration) int r; Py_BEGIN_ALLOW_THREADS - r = tcsendbreak(fd, duration); + r = tcsendbreak(fd, duration); Py_END_ALLOW_THREADS if (r == -1) { @@ -280,7 +280,7 @@ termios_tcdrain_impl(PyObject *module, int fd) int r; Py_BEGIN_ALLOW_THREADS - r = tcdrain(fd); + r = tcdrain(fd); Py_END_ALLOW_THREADS if (r == -1) { @@ -312,7 +312,7 @@ termios_tcflush_impl(PyObject *module, int fd, int queue) int r; Py_BEGIN_ALLOW_THREADS - r = tcflush(fd, queue); + r = tcflush(fd, queue); Py_END_ALLOW_THREADS if (r == -1) { @@ -344,7 +344,7 @@ termios_tcflow_impl(PyObject *module, int fd, int action) int r; Py_BEGIN_ALLOW_THREADS - r = tcflow(fd, action); + r = tcflow(fd, action); Py_END_ALLOW_THREADS if (r == -1) { @@ -375,7 +375,7 @@ termios_tcgetwinsize_impl(PyObject *module, int fd) int r; Py_BEGIN_ALLOW_THREADS - r = ioctl(fd, TIOCGWINSZ, &w); + r = ioctl(fd, TIOCGWINSZ, &w); Py_END_ALLOW_THREADS if (r == -1) { @@ -400,7 +400,7 @@ termios_tcgetwinsize_impl(PyObject *module, int fd) int r; Py_BEGIN_ALLOW_THREADS - r = ioctl(fd, TIOCGSIZE, &s); + r = ioctl(fd, TIOCGSIZE, &s); Py_END_ALLOW_THREADS if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); @@ -485,7 +485,7 @@ termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz) int r; Py_BEGIN_ALLOW_THREADS - r = ioctl(fd, TIOCSWINSZ, &w); + r = ioctl(fd, TIOCSWINSZ, &w); Py_END_ALLOW_THREADS if (r == -1) { @@ -498,7 +498,7 @@ termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz) int r; /* Get the old ttysize because it might have more fields. */ Py_BEGIN_ALLOW_THREADS - r = ioctl(fd, TIOCGSIZE, &s); + r = ioctl(fd, TIOCGSIZE, &s); Py_END_ALLOW_THREADS if (r == -1) { @@ -514,7 +514,7 @@ termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz) } Py_BEGIN_ALLOW_THREADS - r = ioctl(fd, TIOCSSIZE, &s); + r = ioctl(fd, TIOCSSIZE, &s); Py_END_ALLOW_THREADS if (r == -1) {