claytonwramsey / dumpster

Cycle-tracking garbage collector library for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cycles, Gc as Deref during Drop

ijackson opened this issue · comments

I read your blog post. Cool stuff.

I was curious, so I tried the program below. I didn't expect it to work :-). and indeed it panics, saying "thread 'main' panicked at 'dereferencing GC to already-collected object',".

I think that it would be useful to document that dereferencing a Gc for a GC'd object can crash. AFAICT this can only occur if a Gc contained within a T is accessed in T's drop impl. Am I right? (A determined programmer could of course, having gained access to a "bad" Gc in a drop impl, break things elsewhere by feeding them the bad Gc.)

Also, maybe some people doing funky stuff during drop would want a try deref method. I suggest impl Gc<T> { fn try_deref(this: &Self) -> Option<&T>

use std::cell::RefCell;

use dumpster::{Collectable, unsync::Gc};

#[derive(Collectable, Debug)]
struct Loopy {
    value: u32,
    loopy: RefCell<Option<Gc<Loopy>>>,
}

impl Drop for Loopy {
    fn drop(&mut self) {
        eprintln!(
            "drop {:?} {:?}",
            self.value,
            self.loopy.borrow().as_ref().map(|gcl| gcl.value),
        );
    }
}

fn main() {
    let a = Gc::new(Loopy {
        value: 42,
        loopy: None.into(),
    });
    let b = Gc::new(Loopy {
        value: 66,
        loopy: None.into(),
    });
    *a.loopy.borrow_mut() = Some(b.clone());
    *b.loopy.borrow_mut() = Some(a.clone());
    drop(a);
    drop(b);
    eprintln!("returning from main");
}

I believe you're correct - dead Gcs can only be created by attempting to access a Gc during its Drop impl. I'll likely rewrite the code for handling dead Gcs in the near future.

Thanks for the recommendation on try_deref. I'll include it in the next release.

I just finished implementing try_deref and try_clone on both Gcs. Feel free to take a look. I'll publish this version soon(ish), whenever I feel like I've ironed out everything.

Looks good to me!

I had one observation: should Clone on a dead Gc give you another dead Gc instead? Having Clone panic seems rather poor b- ut on the other hand propagating the explosive Gc seems worse. So my feeling is that you've done it the best way but I thought I'd mention it.