5
5
#include "pycore_pyerrors.h" // _PyErr_Fetch()
6
6
#include "pycore_pylifecycle.h" // _PyErr_Print()
7
7
#include "pycore_initconfig.h" // _PyStatus_OK()
8
+ #include "pycore_interp.h" // _Py_RunGC()
8
9
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
9
10
10
11
/*
@@ -69,7 +70,8 @@ COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
69
70
&& _Py_ThreadCanHandleSignals (interp ))
70
71
| (_Py_atomic_load_relaxed_int32 (& ceval2 -> pending .calls_to_do )
71
72
&& _Py_ThreadCanHandlePendingCalls ())
72
- | ceval2 -> pending .async_exc );
73
+ | ceval2 -> pending .async_exc
74
+ | _Py_atomic_load_relaxed_int32 (& ceval2 -> gc_scheduled ));
73
75
}
74
76
75
77
@@ -938,6 +940,7 @@ _Py_HandlePending(PyThreadState *tstate)
938
940
{
939
941
_PyRuntimeState * const runtime = & _PyRuntime ;
940
942
struct _ceval_runtime_state * ceval = & runtime -> ceval ;
943
+ struct _ceval_state * interp_ceval_state = & tstate -> interp -> ceval ;
941
944
942
945
/* Pending signals */
943
946
if (_Py_atomic_load_relaxed_int32 (& ceval -> signals_pending )) {
@@ -947,20 +950,26 @@ _Py_HandlePending(PyThreadState *tstate)
947
950
}
948
951
949
952
/* Pending calls */
950
- struct _ceval_state * ceval2 = & tstate -> interp -> ceval ;
951
- if (_Py_atomic_load_relaxed_int32 (& ceval2 -> pending .calls_to_do )) {
953
+ if (_Py_atomic_load_relaxed_int32 (& interp_ceval_state -> pending .calls_to_do )) {
952
954
if (make_pending_calls (tstate -> interp ) != 0 ) {
953
955
return -1 ;
954
956
}
955
957
}
956
958
959
+ /* GC scheduled to run */
960
+ if (_Py_atomic_load_relaxed_int32 (& interp_ceval_state -> gc_scheduled )) {
961
+ _Py_atomic_store_relaxed (& interp_ceval_state -> gc_scheduled , 0 );
962
+ COMPUTE_EVAL_BREAKER (tstate -> interp , ceval , interp_ceval_state );
963
+ _Py_RunGC (tstate );
964
+ }
965
+
957
966
/* GIL drop request */
958
- if (_Py_atomic_load_relaxed_int32 (& ceval2 -> gil_drop_request )) {
967
+ if (_Py_atomic_load_relaxed_int32 (& interp_ceval_state -> gil_drop_request )) {
959
968
/* Give another thread a chance */
960
969
if (_PyThreadState_Swap (& runtime -> gilstate , NULL ) != tstate ) {
961
970
Py_FatalError ("tstate mix-up" );
962
971
}
963
- drop_gil (ceval , ceval2 , tstate );
972
+ drop_gil (ceval , interp_ceval_state , tstate );
964
973
965
974
/* Other threads may run now */
966
975
@@ -981,16 +990,17 @@ _Py_HandlePending(PyThreadState *tstate)
981
990
return -1 ;
982
991
}
983
992
984
- #ifdef MS_WINDOWS
985
- // bpo-42296: On Windows, _PyEval_SignalReceived() can be called in a
986
- // different thread than the Python thread, in which case
993
+
994
+ // It is possible that some of the conditions that trigger the eval breaker
995
+ // are called in a different thread than the Python thread. An example of
996
+ // this is bpo-42296: On Windows, _PyEval_SignalReceived() can be called in
997
+ // a different thread than the Python thread, in which case
987
998
// _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the
988
999
// current Python thread with the correct _Py_ThreadCanHandleSignals()
989
1000
// value. It prevents to interrupt the eval loop at every instruction if
990
1001
// the current Python thread cannot handle signals (if
991
1002
// _Py_ThreadCanHandleSignals() is false).
992
- COMPUTE_EVAL_BREAKER (tstate -> interp , ceval , ceval2 );
993
- #endif
1003
+ COMPUTE_EVAL_BREAKER (tstate -> interp , ceval , interp_ceval_state );
994
1004
995
1005
return 0 ;
996
1006
}
0 commit comments