Skip to content

Commit 1634d14

Browse files
committed
Add news entry
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
1 parent 47b0d3c commit 1634d14

File tree

4 files changed

+28
-7
lines changed

4 files changed

+28
-7
lines changed

Doc/whatsnew/3.12.rst

+7
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ Other Language Changes
9393
when parsing source code containing null bytes. (Contributed by Pablo Galindo
9494
in :gh:`96670`.)
9595

96+
* The Garbage Collector now runs only on the eval breaker mechanism of the
97+
Python bytecode evaluation loop instead on object allocations. The GC can
98+
also run when :c:func:`PyErr_CheckSignals` is called so C extensions that
99+
need to run for a long time without executing any Python code also have a
100+
chance to execute the GC periodically. (Contributed by Pablo Galindo in
101+
:gh:`97922`.)
102+
96103
New Modules
97104
===========
98105

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
The Garbage Collector now runs only on the eval breaker mechanism of the
2+
Python bytecode evaluation loop instead on object allocations. The GC can
3+
also run when :c:func:`PyErr_CheckSignals` is called so C extensions that
4+
need to run for a long time without executing any Python code also have a
5+
chance to execute the GC periodically.

Modules/gcmodule.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -2255,9 +2255,15 @@ PyObject_IS_GC(PyObject *obj)
22552255
void
22562256
_Py_ScheduleGC(PyInterpreterState *interp)
22572257
{
2258+
GCState *gcstate = &interp->gc;
2259+
if (gcstate->collecting == 1) {
2260+
return;
2261+
}
22582262
struct _ceval_state *ceval = &interp->ceval;
2259-
_Py_atomic_store_relaxed(&ceval->gc_scheduled, 1);
2260-
_Py_atomic_store_relaxed(&ceval->eval_breaker, 1);
2263+
if (!_Py_atomic_load_relaxed(&ceval->gc_scheduled)) {
2264+
_Py_atomic_store_relaxed(&ceval->gc_scheduled, 1);
2265+
_Py_atomic_store_relaxed(&ceval->eval_breaker, 1);
2266+
}
22612267
}
22622268

22632269
void

Python/ceval_gil.c

+8-5
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
7070
&& _Py_ThreadCanHandleSignals(interp))
7171
| (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)
7272
&& _Py_ThreadCanHandlePendingCalls())
73-
| ceval2->pending.async_exc);
73+
| ceval2->pending.async_exc
74+
| _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled));
7475
}
7576

7677

@@ -945,6 +946,7 @@ _Py_HandlePending(PyThreadState *tstate)
945946
if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gc_scheduled)) {
946947
_Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0);
947948
_Py_RunGC(tstate);
949+
COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);
948950
}
949951

950952
/* Pending signals */
@@ -988,16 +990,17 @@ _Py_HandlePending(PyThreadState *tstate)
988990
return -1;
989991
}
990992

991-
#ifdef MS_WINDOWS
992-
// bpo-42296: On Windows, _PyEval_SignalReceived() can be called in a
993-
// 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
994998
// _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the
995999
// current Python thread with the correct _Py_ThreadCanHandleSignals()
9961000
// value. It prevents to interrupt the eval loop at every instruction if
9971001
// the current Python thread cannot handle signals (if
9981002
// _Py_ThreadCanHandleSignals() is false).
9991003
COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);
1000-
#endif
10011004

10021005
return 0;
10031006
}

0 commit comments

Comments
 (0)