summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2019-03-09 06:44:33 (GMT)
committerGitHub <noreply@github.com>2019-03-09 06:44:33 (GMT)
commit8479a3426eb7d1840473f7788e639954363ed37e (patch)
tree9d588c5c30e29d0ab6d6aa0e25c53caba8c5b593 /Python/ceval.c
parent5be45a6105d656c551adeee7770afdc3b806fbb5 (diff)
downloadcpython-8479a3426eb7d1840473f7788e639954363ed37e.zip
cpython-8479a3426eb7d1840473f7788e639954363ed37e.tar.gz
cpython-8479a3426eb7d1840473f7788e639954363ed37e.tar.bz2
bpo-33608: Make sure locks in the runtime are properly re-created. (gh-12245)
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c49
1 files changed, 10 insertions, 39 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 356335a..373cde9 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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;