@@ -322,23 +322,24 @@ _PyEval_SignalReceived(void)
322
322
}
323
323
324
324
static int
325
- _add_pending_call (PyInterpreterState * interp , int (* func )(void * ), void * arg )
325
+ _add_pending_call (PyInterpreterState * interp , unsigned long thread_id , int (* func )(void * ), void * arg )
326
326
{
327
327
int i = interp -> ceval .pending .last ;
328
328
int j = (i + 1 ) % NPENDINGCALLS ;
329
329
if (j == interp -> ceval .pending .first ) {
330
330
return -1 ; /* Queue full */
331
331
}
332
+ interp -> ceval .pending .calls [i ].thread_id = thread_id ;
332
333
interp -> ceval .pending .calls [i ].func = func ;
333
334
interp -> ceval .pending .calls [i ].arg = arg ;
334
335
interp -> ceval .pending .last = j ;
335
336
return 0 ;
336
337
}
337
338
339
+ /* pop one item off the queue while holding the lock */
338
340
static void
339
341
_pop_pending_call (PyInterpreterState * interp , int (* * func )(void * ), void * * arg )
340
342
{
341
- /* pop one item off the queue while holding the lock */
342
343
int i = interp -> ceval .pending .first ;
343
344
if (i == interp -> ceval .pending .last ) {
344
345
return ; /* Queue empty */
@@ -347,13 +348,21 @@ _pop_pending_call(PyInterpreterState *interp, int (**func)(void *), void **arg)
347
348
* func = interp -> ceval .pending .calls [i ].func ;
348
349
* arg = interp -> ceval .pending .calls [i ].arg ;
349
350
interp -> ceval .pending .first = (i + 1 ) % NPENDINGCALLS ;
351
+
352
+ unsigned long thread_id = interp -> ceval .pending .calls [i ].thread_id ;
353
+ if (thread_id && PyThread_get_thread_ident () != thread_id ) {
354
+ // Thread mismatch, so move it to the end of the list
355
+ // and start over.
356
+ _Py_AddPendingCall (interp , thread_id , * func , * arg );
357
+ return ;
358
+ }
350
359
}
351
360
352
361
int
353
362
Py_AddPendingCall (int (* func )(void * ), void * arg )
354
363
{
355
364
PyInterpreterState * interp = _PyRuntime .interpreters .main ;
356
- return _Py_AddPendingCall (interp , func , arg );
365
+ return _Py_AddPendingCall (interp , _PyRuntime . main_thread , func , arg );
357
366
}
358
367
359
368
/* This implementation is thread-safe. It allows
@@ -362,7 +371,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
362
371
*/
363
372
364
373
int
365
- _Py_AddPendingCall (PyInterpreterState * interp , int (* func )(void * ), void * arg )
374
+ _Py_AddPendingCall (PyInterpreterState * interp , unsigned long thread_id , int (* func )(void * ), void * arg )
366
375
{
367
376
/* try a few times for the lock. Since this mechanism is used
368
377
* for signal handling (on the main thread), there is a (slim)
@@ -396,7 +405,7 @@ _Py_AddPendingCall(PyInterpreterState *interp, int (*func)(void *), void *arg)
396
405
goto done ;
397
406
}
398
407
399
- result = _add_pending_call (interp , func , arg );
408
+ result = _add_pending_call (interp , thread_id , func , arg );
400
409
/* signal main loop */
401
410
SIGNAL_PENDING_CALLS (interp );
402
411
0 commit comments