Skip to content

Commit 0090365

Browse files
committed
wip: improve error handling for OOM
Use gc_abort_mark_alive() helper in case of OOM. In addition to freeing the stack, we need to ensure that no object has the alive bit set on it. This also adding missing error handling in the case that propagate_alive_bits() fails.
1 parent 79ea47e commit 0090365

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

Python/gc_free_threading.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,37 @@ mark_alive_stack_push(PyObject *op, _PyObjectStack *stack)
484484
// alive so we don't traverse it a second time.
485485
gc_set_alive(op);
486486
if (_PyObjectStack_Push(stack, op) < 0) {
487-
_PyObjectStack_Clear(stack);
488487
return -1;
489488
}
490489
return 0;
491490
}
492491

492+
static bool
493+
gc_clear_alive_bits(const mi_heap_t *heap, const mi_heap_area_t *area,
494+
void *block, size_t block_size, void *args)
495+
{
496+
PyObject *op = op_from_block(block, args, false);
497+
if (op == NULL) {
498+
return true;
499+
}
500+
if (gc_is_alive(op)) {
501+
gc_clear_alive(op);
502+
}
503+
return true;
504+
}
505+
506+
static void
507+
gc_abort_mark_alive(PyInterpreterState *interp,
508+
struct collection_state *state,
509+
_PyObjectStack *stack)
510+
{
511+
// We failed to allocate memory for "stack" while doing the "mark
512+
// alive" phase. In that case, free the object stack and make sure
513+
// that no objects have the alive bit set.
514+
_PyObjectStack_Clear(stack);
515+
gc_visit_heaps(interp, &gc_clear_alive_bits, &state->base);
516+
}
517+
493518
#ifdef GC_MARK_ALIVE_STACKS
494519
static int
495520
gc_visit_stackref_mark_alive(_PyObjectStack *stack, _PyStackRef stackref)
@@ -901,6 +926,7 @@ mark_alive_from_roots(PyInterpreterState *interp,
901926

902927
#define STACK_PUSH(op) \
903928
if (mark_alive_stack_push(op, &stack) < 0) { \
929+
gc_abort_mark_alive(interp, state, &stack); \
904930
return -1; \
905931
}
906932
STACK_PUSH(interp->sysdict);
@@ -919,13 +945,17 @@ mark_alive_from_roots(PyInterpreterState *interp,
919945
#endif
920946
#ifdef GC_MARK_ALIVE_STACKS
921947
if (gc_visit_thread_stacks_mark_alive(interp, &stack) < 0) {
948+
gc_abort_mark_alive(interp, state, &stack);
922949
return -1;
923950
}
924951
#endif
925952
#undef STACK_PUSH
926953

927954
// Use tp_traverse to find everything reachable from roots.
928-
propagate_alive_bits(&stack);
955+
if (propagate_alive_bits(&stack) < 0) {
956+
gc_abort_mark_alive(interp, state, &stack);
957+
return -1;
958+
}
929959

930960
return 0;
931961
}

0 commit comments

Comments
 (0)