summaryrefslogtreecommitdiffstats
path: root/Parser
diff options
context:
space:
mode:
authorBar Harel <bharel@barharel.com>2024-09-04 15:21:30 (GMT)
committerGitHub <noreply@github.com>2024-09-04 15:21:30 (GMT)
commita4562fedadb73fe1e978dece65c3bcefb4606678 (patch)
treeaf2195c8aa1375ae19fabc9ec34c1855b1fe79d3 /Parser
parentc530ce1e9d336b81c053a5985444b4553fdd7050 (diff)
downloadcpython-a4562fedadb73fe1e978dece65c3bcefb4606678.zip
cpython-a4562fedadb73fe1e978dece65c3bcefb4606678.tar.gz
cpython-a4562fedadb73fe1e978dece65c3bcefb4606678.tar.bz2
gh-123321: Fix Parser/myreadline.c to prevent a segfault during a multi-threaded race (#123323)
Diffstat (limited to 'Parser')
-rw-r--r--Parser/myreadline.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index 1825665..6eab56a 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -392,9 +392,14 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
}
}
- _PyOS_ReadlineTState = tstate;
Py_BEGIN_ALLOW_THREADS
+
+ // GH-123321: We need to acquire the lock before setting
+ // _PyOS_ReadlineTState and after the release of the GIL, otherwise
+ // the variable may be nullified by a different thread or a deadlock
+ // may occur if the GIL is taken in any sub-function.
PyThread_acquire_lock(_PyOS_ReadlineLock, 1);
+ _PyOS_ReadlineTState = tstate;
/* This is needed to handle the unlikely case that the
* interpreter is in interactive mode *and* stdin/out are not
@@ -418,11 +423,13 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
else {
rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, prompt);
}
- Py_END_ALLOW_THREADS
+ // gh-123321: Must set the variable and then release the lock before
+ // taking the GIL. Otherwise a deadlock or segfault may occur.
+ _PyOS_ReadlineTState = NULL;
PyThread_release_lock(_PyOS_ReadlineLock);
- _PyOS_ReadlineTState = NULL;
+ Py_END_ALLOW_THREADS
if (rv == NULL)
return NULL;