Skip to content

Use of GC inside destructors aborts when destructor called from GC #6996

Closed
@bblum

Description

@bblum

Updated example

use std::task;
use std::gc::{GC, Gc};
use std::cell::RefCell;

struct Foo;
impl Drop for Foo {
    fn drop(&mut self) {
        allocate();
    }
}

fn allocate() {
    struct A {
        inner: RefCell<Option<Gc<A>>>,
        other: Foo,
    }
    let a = box(GC) A {
        inner: RefCell::new(None),
        other: Foo,
    };
    *a.inner.borrow_mut() = Some(a.clone());
}

fn main() {
    allocate();
}
failed at 'assertion failed: self.live_allocs.is_null()', /home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/librustrt/local_heap.rs:173
run with `RUST_BACKTRACE=1` to see a backtrace

You've met with a terrible fate, haven't you?

fatal runtime error: Could not unwind stack, error = 5
zsh: illegal hardware instruction (core dumped)  ./foo

Original description

This program crashes:

struct Foo { x: int } // surprisingly, doesn't crash with an empty struct

impl Drop for Foo {
    fn finalize(&self) {
        let _x = @Foo { x: self.x + 1 };
    }
}

fn main() { let _x = @Foo { x: 0 }; }

With the current implementation, the crash message is:

rust: task f46140 ran out of stack
rust: domain main @0xf44a40 root task failed
rust: task f46140 ran out of stack during unwinding
terminate called after throwing an instance of 'rust_task*'
Aborted

But when we switch to tracing GC for @-pointers, I predict a new problem: the destructor won't run until an attempt to allocate another @-pointer fails, at which point @-pointers could no longer be allocatable... and the allocation would fail (even though the amount of live memory in use might be reasonably small). This raises some questions:

  • Should we ban creating new @-pointers in destructors, or does "disable recursive GC" during GC" suffice?
  • Depending on the allocator design, would that also make it unsafe to allocate ~-pointers in destructors?

Related #910.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-destructorsArea: Destructors (`Drop`, …)A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflowsA-type-systemArea: Type systemI-crashIssue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.P-mediumMedium priority

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions