Assure drop is being called

According to https://doc.rust-lang.org/reference/behavior-not-considered-unsafe.html drop() not being called, is ok~ish behaviour for rust.

So far I identified a few cases where this might happen:

  • panics
  • calling std::process::exit

The issue with this in the current pet project is handling device handles abstracted by a library that is not very good at releasing resources, so that has to be done explcitily.

For the panic!() case one can register another intermediate handler cleaning up the handle and forwarding to the original handler.

But for the generic case, how can I assure that a func is called after the main is called? Coming from a C/C++ embedded background there exists some means of exit handlers (depening on the compiler).

How can I achieve the above with rust?

Thanks!

juice related issue

The more specific issue faces is described in https://github.com/spearow/juice/issues/88 but the above is the derived root question :slight_smile:

Some other cases:

  • SIGKILL
  • mem::forget()
  • Leaking a smart pointer, e.g. Box::leak() and dropping the returned reference
  • Creating reference cycles with Rc and Arc

And also a reminder to pre-poop your pants to avoid problems related to just never running destructors.

The linked issue reminds me of a very old issue I created against fuse-rs, where an early termination of an app implementing a VFS would leave FUSE with a dead mount point: https://github.com/zargony/fuse-rs/issues/58

Sorry I couldn't be much more help. This kind of seems like a bug in the OS, and not something Rust can (or should) solve. (But maybe some extra defensive-coding practices could be helpful anyway?)

3 Likes

Actually, sys_common::cleanup() uses closures implemented at_exit_impl of std which can be fed into it with sys_common::push(|| { println!("I am so done")}) (this will panic, since there is no stdout at that point)

dunno how I missed that earlier on.. let's see if it works :slight_smile: - and for which of the mentioned cases (@parasyte thanks, I did not have all of them on my radar!)

You should be able to use all the same mechanisms as you would in C. For example the libc crate exposes bindings to atexit() on *nix machines. On Windows machines you can use DllMain for the same purpose.

A lot of these mechanisms are exposed by the OS instead of the compiler, so they should Just Work.

$ cd /tmp && cargo new thingy
$ cargo add libc
$ cat src/main.rs
extern crate libc;

fn main() {
    unsafe {
        libc::atexit(before_process_exit);
    }

    println!("Hello, world!");
}

extern "C" fn before_process_exit() {
    unsafe {
        libc::printf(b"Exiting!\n\0".as_ptr() as *const libc::c_char);
    }
}
$ cargo run
   Compiling thingy v0.1.0 (/tmp/thingy)
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/thingy`
Hello, world!
Exiting!
1 Like

My particular issue turned out to be independent of this question, but a multi lib initialization sequence violation

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.