diff options
author | Bar Harel <bharel@barharel.com> | 2024-09-04 15:21:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-04 15:21:30 (GMT) |
commit | a4562fedadb73fe1e978dece65c3bcefb4606678 (patch) | |
tree | af2195c8aa1375ae19fabc9ec34c1855b1fe79d3 /Parser | |
parent | c530ce1e9d336b81c053a5985444b4553fdd7050 (diff) | |
download | cpython-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.c | 13 |
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; |