bpo-33608: Make sure locks in the runtime are properly re-created. (… · python/cpython@8479a34 (original) (raw)
`@@ -174,10 +174,10 @@ PyEval_InitThreads(void)
`
174
174
`PyThread_init_thread();
`
175
175
`create_gil();
`
176
176
`take_gil(_PyThreadState_GET());
`
177
``
`-
// Set it to the ID of the main thread of the main interpreter.
`
178
``
`-
_PyRuntime.main_thread = PyThread_get_thread_ident();
`
179
``
`-
if (!_PyRuntime.ceval.pending.lock) {
`
180
``
`-
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
``
177
+
``
178
`+
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
``
179
`+
if (_PyRuntime.ceval.pending.lock == NULL) {
`
``
180
`+
return Py_FatalError("Can't initialize threads for pending calls");
`
181
181
` }
`
182
182
`}
`
183
183
``
`@@ -246,8 +246,11 @@ PyEval_ReInitThreads(void)
`
246
246
`return;
`
247
247
`recreate_gil();
`
248
248
`take_gil(current_tstate);
`
249
``
`-
_PyRuntime.main_thread = PyThread_get_thread_ident();
`
``
249
+
250
250
`_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
``
251
`+
if (_PyRuntime.ceval.pending.lock == NULL) {
`
``
252
`+
Py_FatalError("Can't initialize threads for pending calls");
`
``
253
`+
}
`
251
254
``
252
255
`/* Destroy all threads except the current one */
`
253
256
`_PyThreadState_DeleteExcept(current_tstate);
`
`@@ -362,35 +365,12 @@ _pop_pending_call(int (**func)(void *), void **arg)
`
362
365
`int
`
363
366
`Py_AddPendingCall(int (*func)(void *), void *arg)
`
364
367
`{
`
365
``
`-
PyThread_type_lock lock = _PyRuntime.ceval.pending.lock;
`
366
``
-
367
``
`-
/* try a few times for the lock. Since this mechanism is used
`
368
``
`-
- for signal handling (on the main thread), there is a (slim)
`
369
``
`-
- chance that a signal is delivered on the same thread while we
`
370
``
`-
- hold the lock during the Py_MakePendingCalls() function.
`
371
``
`-
- This avoids a deadlock in that case.
`
372
``
`-
- Note that signals can be delivered on any thread. In particular,
`
373
``
`-
- on Windows, a SIGINT is delivered on a system-created worker
`
374
``
`-
- thread.
`
375
``
`-
- We also check for lock being NULL, in the unlikely case that
`
376
``
`-
- this function is called before any bytecode evaluation takes place.
`
377
``
`-
*/
`
378
``
`-
if (lock != NULL) {
`
379
``
`-
int i;
`
380
``
`-
for (i = 0; i<100; i++) {
`
381
``
`-
if (PyThread_acquire_lock(lock, NOWAIT_LOCK))
`
382
``
`-
break;
`
383
``
`-
}
`
384
``
`-
if (i == 100)
`
385
``
`-
return -1;
`
386
``
`-
}
`
387
``
-
``
368
`+
PyThread_acquire_lock(_PyRuntime.ceval.pending.lock, WAIT_LOCK);
`
388
369
`int result = _push_pending_call(func, arg);
`
``
370
`+
PyThread_release_lock(_PyRuntime.ceval.pending.lock);
`
389
371
``
390
372
`/* signal main loop */
`
391
373
`SIGNAL_PENDING_CALLS();
`
392
``
`-
if (lock != NULL)
`
393
``
`-
PyThread_release_lock(lock);
`
394
374
`return result;
`
395
375
`}
`
396
376
``
`@@ -439,15 +419,6 @@ make_pending_calls(void)
`
439
419
`UNSIGNAL_PENDING_CALLS();
`
440
420
`int res = 0;
`
441
421
``
442
``
`-
if (!_PyRuntime.ceval.pending.lock) {
`
443
``
`-
/* initial allocation of the lock */
`
444
``
`-
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
445
``
`-
if (_PyRuntime.ceval.pending.lock == NULL) {
`
446
``
`-
res = -1;
`
447
``
`-
goto error;
`
448
``
`-
}
`
449
``
`-
}
`
450
``
-
451
422
`/* perform a bounded number of calls, in case of recursion */
`
452
423
`for (int i=0; i<NPENDINGCALLS; i++) {
`
453
424
`int (*func)(void *) = NULL;
`