Skip to content

Commit

Permalink
Add news entry
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
  • Loading branch information
pablogsal committed Oct 5, 2022
1 parent 47b0d3c commit 1634d14
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 7 deletions.
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ Other Language Changes
when parsing source code containing null bytes. (Contributed by Pablo Galindo
in :gh:`96670`.)

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

New Modules
===========

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The Garbage Collector now runs only on the eval breaker mechanism of the
Python bytecode evaluation loop instead on object allocations. The GC can
also run when :c:func:`PyErr_CheckSignals` is called so C extensions that
need to run for a long time without executing any Python code also have a
chance to execute the GC periodically.
10 changes: 8 additions & 2 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2255,9 +2255,15 @@ PyObject_IS_GC(PyObject *obj)
void
_Py_ScheduleGC(PyInterpreterState *interp)
{
GCState *gcstate = &interp->gc;
if (gcstate->collecting == 1) {
return;
}
struct _ceval_state *ceval = &interp->ceval;
_Py_atomic_store_relaxed(&ceval->gc_scheduled, 1);
_Py_atomic_store_relaxed(&ceval->eval_breaker, 1);
if (!_Py_atomic_load_relaxed(&ceval->gc_scheduled)) {
_Py_atomic_store_relaxed(&ceval->gc_scheduled, 1);
_Py_atomic_store_relaxed(&ceval->eval_breaker, 1);
}
}

void
Expand Down
13 changes: 8 additions & 5 deletions Python/ceval_gil.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
&& _Py_ThreadCanHandleSignals(interp))
| (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)
&& _Py_ThreadCanHandlePendingCalls())
| ceval2->pending.async_exc);
| ceval2->pending.async_exc
| _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled));
}


Expand Down Expand Up @@ -945,6 +946,7 @@ _Py_HandlePending(PyThreadState *tstate)
if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gc_scheduled)) {
_Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0);
_Py_RunGC(tstate);
COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);
}

/* Pending signals */
Expand Down Expand Up @@ -988,16 +990,17 @@ _Py_HandlePending(PyThreadState *tstate)
return -1;
}

#ifdef MS_WINDOWS
// bpo-42296: On Windows, _PyEval_SignalReceived() can be called in a
// different thread than the Python thread, in which case

// It is possible that some of the conditions that trigger the eval breaker
// are called in a different thread than the Python thread. An example of
// this is bpo-42296: On Windows, _PyEval_SignalReceived() can be called in
// a different thread than the Python thread, in which case
// _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the
// current Python thread with the correct _Py_ThreadCanHandleSignals()
// value. It prevents to interrupt the eval loop at every instruction if
// the current Python thread cannot handle signals (if
// _Py_ThreadCanHandleSignals() is false).
COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);
#endif

return 0;
}
Expand Down

0 comments on commit 1634d14

Please sign in to comment.