mirror of
https://github.com/python/cpython.git
synced 2025-11-01 14:11:41 +00:00
bpo-33608: Make sure locks in the runtime are properly re-created. (gh-12245)
This commit is contained in:
parent
5be45a6105
commit
8479a3426e
4 changed files with 40 additions and 40 deletions
|
|
@ -174,10 +174,10 @@ PyEval_InitThreads(void)
|
|||
PyThread_init_thread();
|
||||
create_gil();
|
||||
take_gil(_PyThreadState_GET());
|
||||
// Set it to the ID of the main thread of the main interpreter.
|
||||
_PyRuntime.main_thread = PyThread_get_thread_ident();
|
||||
if (!_PyRuntime.ceval.pending.lock) {
|
||||
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
|
||||
|
||||
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
|
||||
if (_PyRuntime.ceval.pending.lock == NULL) {
|
||||
return Py_FatalError("Can't initialize threads for pending calls");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,8 +246,11 @@ PyEval_ReInitThreads(void)
|
|||
return;
|
||||
recreate_gil();
|
||||
take_gil(current_tstate);
|
||||
_PyRuntime.main_thread = PyThread_get_thread_ident();
|
||||
|
||||
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
|
||||
if (_PyRuntime.ceval.pending.lock == NULL) {
|
||||
Py_FatalError("Can't initialize threads for pending calls");
|
||||
}
|
||||
|
||||
/* Destroy all threads except the current one */
|
||||
_PyThreadState_DeleteExcept(current_tstate);
|
||||
|
|
@ -362,35 +365,12 @@ _pop_pending_call(int (**func)(void *), void **arg)
|
|||
int
|
||||
Py_AddPendingCall(int (*func)(void *), void *arg)
|
||||
{
|
||||
PyThread_type_lock lock = _PyRuntime.ceval.pending.lock;
|
||||
|
||||
/* try a few times for the lock. Since this mechanism is used
|
||||
* for signal handling (on the main thread), there is a (slim)
|
||||
* chance that a signal is delivered on the same thread while we
|
||||
* hold the lock during the Py_MakePendingCalls() function.
|
||||
* This avoids a deadlock in that case.
|
||||
* Note that signals can be delivered on any thread. In particular,
|
||||
* on Windows, a SIGINT is delivered on a system-created worker
|
||||
* thread.
|
||||
* We also check for lock being NULL, in the unlikely case that
|
||||
* this function is called before any bytecode evaluation takes place.
|
||||
*/
|
||||
if (lock != NULL) {
|
||||
int i;
|
||||
for (i = 0; i<100; i++) {
|
||||
if (PyThread_acquire_lock(lock, NOWAIT_LOCK))
|
||||
break;
|
||||
}
|
||||
if (i == 100)
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyThread_acquire_lock(_PyRuntime.ceval.pending.lock, WAIT_LOCK);
|
||||
int result = _push_pending_call(func, arg);
|
||||
PyThread_release_lock(_PyRuntime.ceval.pending.lock);
|
||||
|
||||
/* signal main loop */
|
||||
SIGNAL_PENDING_CALLS();
|
||||
if (lock != NULL)
|
||||
PyThread_release_lock(lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -439,15 +419,6 @@ make_pending_calls(void)
|
|||
UNSIGNAL_PENDING_CALLS();
|
||||
int res = 0;
|
||||
|
||||
if (!_PyRuntime.ceval.pending.lock) {
|
||||
/* initial allocation of the lock */
|
||||
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
|
||||
if (_PyRuntime.ceval.pending.lock == NULL) {
|
||||
res = -1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform a bounded number of calls, in case of recursion */
|
||||
for (int i=0; i<NPENDINGCALLS; i++) {
|
||||
int (*func)(void *) = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue