FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-153014: Fix data race on the GC debug flag in free-threading builds by tonghuaroot · Pull Request #153015 · python/cpython · GitHub

Repository navigation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix a data race on the garbage collector debug flag in free-threading builds:
:func:`gc.set_debug` and :func:`gc.get_debug` now access it atomically.
5 changes: 3 additions & 2 deletions Modules/gcmodule.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Python.h"
#include "pycore_gc.h"
#include "pycore_object.h" // _PyObject_IS_GC()
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_INT_RELAXED()
#include "pycore_pystate.h" // _PyInterpreterState_GET()

typedef struct _gc_runtime_state GCState;
Expand Down Expand Up @@ -116,7 +117,7 @@ gc_set_debug_impl(PyObject *module, int flags)
/*[clinic end generated code: output=7c8366575486b228 input=5e5ce15e84fbed15]*/
{
GCState *gcstate = get_gc_state();
gcstate->debug = flags;
FT_ATOMIC_STORE_INT_RELAXED(gcstate->debug, flags);
Py_RETURN_NONE;
}

Expand All @@ -131,7 +132,7 @@ gc_get_debug_impl(PyObject *module)
/*[clinic end generated code: output=91242f3506cd1e50 input=91a101e1c3b98366]*/
{
GCState *gcstate = get_gc_state();
return gcstate->debug;
return FT_ATOMIC_LOAD_INT_RELAXED(gcstate->debug);
}

/*[clinic input]
Expand Down
23 changes: 14 additions & 9 deletions Python/gc_free_threading.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "pycore_interpframe.h" // _PyFrame_GetLocalsArray()
#include "pycore_list.h" // _PyList_GetItemRef()
#include "pycore_object_alloc.h" // _PyObject_MallocWithType()
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_INT_RELAXED()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_tstate.h" // _PyThreadStateImpl
#include "pycore_tuple.h" // _PyTuple_MaybeUntrack()
Expand Down Expand Up @@ -1738,6 +1739,7 @@ delete_garbage(struct collection_state *state)
{
PyThreadState *tstate = _PyThreadState_GET();
GCState *gcstate = state->gcstate;
int debug = FT_ATOMIC_LOAD_INT_RELAXED(gcstate->debug);

assert(!_PyErr_Occurred(tstate));

Expand All @@ -1760,7 +1762,7 @@ delete_garbage(struct collection_state *state)

state->collected++;

if (gcstate->debug & _PyGC_DEBUG_SAVEALL) {
if (debug & _PyGC_DEBUG_SAVEALL) {
assert(gcstate->garbage != NULL);
if (PyList_Append(gcstate->garbage, op) < 0) {
_PyErr_Clear(tstate);
Expand All @@ -1786,16 +1788,17 @@ handle_legacy_finalizers(struct collection_state *state)
{
GCState *gcstate = state->gcstate;
assert(gcstate->garbage != NULL);
int debug = FT_ATOMIC_LOAD_INT_RELAXED(gcstate->debug);

PyObject *op;
while ((op = worklist_pop(&state->legacy_finalizers)) != NULL) {
state->uncollectable++;

if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) {
if (debug & _PyGC_DEBUG_UNCOLLECTABLE) {
debug_cycle("uncollectable", op);
}

if ((gcstate->debug & _PyGC_DEBUG_SAVEALL) || has_legacy_finalizer(op)) {
if ((debug & _PyGC_DEBUG_SAVEALL) || has_legacy_finalizer(op)) {
if (PyList_Append(gcstate->garbage, op) < 0) {
PyErr_Clear();
}
Expand Down Expand Up @@ -2146,7 +2149,7 @@ gc_collect_internal(PyInterpreterState *interp, struct collection_state *state,
bool needs_resurrection_check = state->objs_to_decref.head != 0;

// Print debugging information.
if (interp->gc.debug & _PyGC_DEBUG_COLLECTABLE) {
if (FT_ATOMIC_LOAD_INT_RELAXED(interp->gc.debug) & _PyGC_DEBUG_COLLECTABLE) {
needs_resurrection_check = true;
PyObject *op;
WORKSTACK_FOR_EACH(&state->unreachable, op) {
Expand Down Expand Up @@ -2260,7 +2263,8 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
invoke_gc_callback(tstate, "start", generation, 0, 0, 0, 0.0);
}

if (gcstate->debug & _PyGC_DEBUG_STATS) {
int debug = FT_ATOMIC_LOAD_INT_RELAXED(gcstate->debug);
if (debug & _PyGC_DEBUG_STATS) {
PySys_WriteStderr("gc: collecting generation %d...\n", generation);
show_stats_each_generations(gcstate);
}
Expand All @@ -2287,7 +2291,7 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
(void)PyTime_PerfCounterRaw(&stop);
double duration = PyTime_AsSecondsDouble(stop - start);

if (gcstate->debug & _PyGC_DEBUG_STATS) {
if (debug & _PyGC_DEBUG_STATS) {
PySys_WriteStderr(
"gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n",
n+m, n, duration);
Expand Down Expand Up @@ -2618,10 +2622,11 @@ void
_PyGC_DumpShutdownStats(PyInterpreterState *interp)
{
GCState *gcstate = &interp->gc;
if (!(gcstate->debug & _PyGC_DEBUG_SAVEALL)
int debug = FT_ATOMIC_LOAD_INT_RELAXED(gcstate->debug);
if (!(debug & _PyGC_DEBUG_SAVEALL)
&& gcstate->garbage != NULL && PyList_GET_SIZE(gcstate->garbage) > 0) {
const char *message;
if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) {
if (debug & _PyGC_DEBUG_UNCOLLECTABLE) {
message = "gc: %zd uncollectable objects at shutdown";
}
else {
Expand All @@ -2637,7 +2642,7 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp)
{
PyErr_FormatUnraisable("Exception ignored in GC shutdown");
}
if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) {
if (debug & _PyGC_DEBUG_UNCOLLECTABLE) {
PyObject *repr = NULL, *bytes = NULL;
repr = PyObject_Repr(gcstate->garbage);
if (!repr || !(bytes = PyUnicode_EncodeFSDefault(repr))) {
Expand Down
Loading

Back | FazBrowse Home | New Git URL