28
28
PyAPI_DATA (PyThreadState * ) _PyOS_ReadlineTState ;
29
29
PyThreadState * _PyOS_ReadlineTState = NULL ;
30
30
31
- static PyThread_type_lock _PyOS_ReadlineLock = NULL ;
31
+ static PyMutex _PyOS_ReadlineLock ;
32
32
33
33
int (* PyOS_InputHook )(void ) = NULL ;
34
34
@@ -373,34 +373,22 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
373
373
size_t len ;
374
374
375
375
PyThreadState * tstate = _PyThreadState_GET ();
376
- if (_PyOS_ReadlineTState == tstate ) {
376
+ if (_Py_atomic_load_ptr_relaxed ( & _PyOS_ReadlineTState ) == tstate ) {
377
377
PyErr_SetString (PyExc_RuntimeError ,
378
378
"can't re-enter readline" );
379
379
return NULL ;
380
380
}
381
381
382
-
382
+ // GH-123321: We need to acquire the lock before setting
383
+ // _PyOS_ReadlineTState, otherwise the variable may be nullified by a
384
+ // different thread.
385
+ Py_BEGIN_ALLOW_THREADS
386
+ PyMutex_Lock (& _PyOS_ReadlineLock );
387
+ _Py_atomic_store_ptr_relaxed (& _PyOS_ReadlineTState , tstate );
383
388
if (PyOS_ReadlineFunctionPointer == NULL ) {
384
389
PyOS_ReadlineFunctionPointer = PyOS_StdioReadline ;
385
390
}
386
391
387
- if (_PyOS_ReadlineLock == NULL ) {
388
- _PyOS_ReadlineLock = PyThread_allocate_lock ();
389
- if (_PyOS_ReadlineLock == NULL ) {
390
- PyErr_SetString (PyExc_MemoryError , "can't allocate lock" );
391
- return NULL ;
392
- }
393
- }
394
-
395
- Py_BEGIN_ALLOW_THREADS
396
-
397
- // GH-123321: We need to acquire the lock before setting
398
- // _PyOS_ReadlineTState and after the release of the GIL, otherwise
399
- // the variable may be nullified by a different thread or a deadlock
400
- // may occur if the GIL is taken in any sub-function.
401
- PyThread_acquire_lock (_PyOS_ReadlineLock , 1 );
402
- _PyOS_ReadlineTState = tstate ;
403
-
404
392
/* This is needed to handle the unlikely case that the
405
393
* interpreter is in interactive mode *and* stdin/out are not
406
394
* a tty. This can happen, for example if python is run like
@@ -426,9 +414,8 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
426
414
427
415
// gh-123321: Must set the variable and then release the lock before
428
416
// taking the GIL. Otherwise a deadlock or segfault may occur.
429
- _PyOS_ReadlineTState = NULL ;
430
- PyThread_release_lock (_PyOS_ReadlineLock );
431
-
417
+ _Py_atomic_store_ptr_relaxed (& _PyOS_ReadlineTState , NULL );
418
+ PyMutex_Unlock (& _PyOS_ReadlineLock );
432
419
Py_END_ALLOW_THREADS
433
420
434
421
if (rv == NULL)
0 commit comments