rust-ctor: ctor not running for statically linked libraries

Hi,

I have an issue with the following setup:

  • app crate defines the binary to produce
  • lib crate defines a rust standard library

When using #[ctor] attribute inside the crate lib, it is not called when running the binary built with app.

Using a rust library dependency statically link it so it should also include the ctor function, but it does not seems to be the case.

Am I missing something or is this an unsupported use case?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 15 (8 by maintainers)

Most upvoted comments

I can reproduce this on macOS Mojave and Rust 1.39.0 as well. However, it seems that I am able to get the constructor to run at least with the following minimal application:

//! lib.rs

#[ctor::ctor]
fn on_startup() {
    println!("Starting up!");
}

#[ctor::dtor]
unsafe fn on_shutdown() {
    libc::printf("Shutting down!\n\0".as_ptr() as *const i8);
}

pub fn unused() {}
//! main.rs

use foo::unused;

fn main() {
    unused();
    println!("Running");
}

The output produced by this application is:

Starting up!
Running

If I comment out the unused() call in main.rs, the application now produces the following output instead:

Running

I was unable to get the destructor working with the #[dtor] macro, but if you replace the definition of the foo::on_shutdown() function with this instead:

extern "C" fn on_shutdown() {
    unsafe { libc::printf("Shutting down!\n\0".as_ptr() as *const i8) };
}

And then add the following call to libc::atexit() to the foo::on_startup() constructor:

unsafe { libc::atexit(on_shutdown) };

The application now works as expected:

Starting up!
Running
Shutting down!

In short, it seems that a few tweaks to the way your application is written will get the constructor and destructor to run:

  1. Your main.rs must call at least one function or inherent struct method from lib.rs for #[ctor] to register properly. Importing static and const values in the main.rs doesn’t seem to help.
  2. #[dtor] doesn’t seem to work at all. Register it manually with libc::atexit() in your #[ctor] function.

I’m not sure what is going on, but I am also leaning towards the possibility of an issue with Rust or LLVM.