Expand description
§dtor
Shutdown functions for Rust (like __attribute__((destructor)) in C/C++) for
Linux, OSX, Windows, mobile (iOS/Android), WASM, BSD/BSD-likes and many other
platforms.
use dtor::dtor;
#[dtor(unsafe)]
fn foo() {
println!("Life after main!");
}§Examples
Print a message at shutdown time.
#[dtor(unsafe)]
fn shutdown() {
// Using println! or eprintln! here may panic as Rust may have
// shut down some stdlib services at this time.
libc_println!("Shutting down!");
}§Platform Support
| Platform | Link Section | at_binary_exit | at_module_exit |
|---|---|---|---|
| Linux | .fini_array | Yes (atexit) | Yes (__cxa_atexit) |
| MacOS | .mod_term_func 🍎 | Yes (atexit) | Yes (__cxa_atexit) |
| Windows | .CRT$XPU 🪟 | No | Yes (atexit) |
| AIX | No 🔵 | Yes | Yes |
| Other POSIX-like platforms | .fini_array/.dtors | Yes (atexit) | Yes (__cxa_atexit) |
Notes:
- 🍎 Not recommended. Apple platforms no longer call
mod_term_funcfunctions. - 🪟 Not recommended. Windows platforms may not reliably call functions in link sections, unless a binary is built with a static CRT.
- 🔵 Link sections are not supported on AIX, but the
platform calls functions with the prefix
__sinitand__stermat startup and shutdown respectively.
§Shutdown Method (#[dtor(method = ...)])
The #[dtor] macro supports multiple registration strategies via
#[dtor(method = ...)]. The best choice is platform-dependent:
#[dtor](no method specified): Use the platform’s most reliable method:at_module_exiton Windows and Apple platforms, andlinkeron others.unload: Run on module unload (library unload or process exit) using the platform’s default unload method.term: Run on process termination only using the platform’s default termination method. Not recommended: code may be unloaded before the dtor runs.at_module_exit: Register using__cxa_atexit(non-Windows) oratexit(Windows) so the dtor runs when the module unloads.at_binary_exit: Register to run at process exit (unsupported on Windows).linker: Register using the platform’s linker mechanism (link_sectionon all platforms with the exception ofexport_name_prefixon AIX). Unsupported on Apple platforms.
Default:
- Apple and Windows default to
at_module_exit - Most other platforms default to
linker
Examples:
use dtor::dtor;
/// Use `at_module_exit` on all platforms
#[dtor(unsafe, method = at_module_exit)]
fn shutdown() {}use dtor::dtor;
/// Use `link_section` with a section name of `.dtors` on most platforms,
/// and `export_name_prefix` on AIX
#[dtor(unsafe, method = linker, link_section = ".dtors")]
fn shutdown() {}§Under the Hood
The #[dtor] macro effectively creates a constructor that calls libc::atexit
with the provided function, i.e. roughly equivalent to:
#[ctor]
fn dtor_atexit() {
libc::atexit(dtor);
}§Crate Features
| Cargo feature | Description |
|---|---|
no_warn_on_missing_unsafe | Do not warn when a ctor or dtor is missing the unsafe keyword. |
proc_macro | Enable support for the proc-macro #[dtor] attribute. The declarative form (dtor!(...)) is always available. It is recommended that crates re-exporting the dtor macro disable this feature and only use the declarative form. |
std | Enable support for the standard library. |
used_linker | Applies used(linker) to all dtor-generated functions. Requires nightly and feature(used_with_arg). |
§Macro Attributes
| Attribute | Description |
|---|---|
anonymous |
Make the ctor function anonymous. |
crate_path = $path : pat |
Specify a custom crate path for the |
ctor(export_name_prefix = $ctor_export_name_prefix_str : literal) |
Specify a custom export name prefix for the constructor function. If specified, an export with the given prefix will be generated in the form:
|
ctor(link_section = $ctor_link_section_name : literal) |
Place the initialization function pointer in a custom link section. |
export_name_prefix = $export_name_prefix_str : literal |
Specify a custom export name prefix for the destructor function. If specified, an export with the given prefix will be generated in the form:
|
link_section = $section : literal |
Place the destructor function pointer in a custom link section. |
method = $method_id : ident |
Specify the dtor method.
|
unsafe |
Marks a ctor/dtor as unsafe. |
used(linker) |
Mark generated functions for this |
§Defaults
§ctor_export_name_prefix
#[cfg(target_os = "aix")]
ctor_export_name_prefix = "__sinit80000000"
// default
ctor_export_name_prefix = ()§ctor_link_section
#[cfg(target_vendor = "apple")]
ctor_link_section = "__DATA,__mod_init_func,mod_init_funcs"
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd",
target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly",
target_os = "illumos", target_os = "haiku", target_os = "vxworks", target_os =
"nto", target_family = "wasm"))]
ctor_link_section = ".init_array"
#[cfg(target_os = "none")]
ctor_link_section = ".init_array"
#[cfg(target_arch = "xtensa")]
ctor_link_section = ".ctors"
#[cfg(all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc")))]
ctor_link_section = ".CRT$XCU"
#[cfg(all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc"))))]
ctor_link_section = ".ctors"
#[cfg(all(target_os = "aix"))]
ctor_link_section = ()
// default
ctor_link_section = (compile_error! ("Unsupported target for #[ctor]"))§default_term_method
#[cfg(target_vendor = "pc")]
default_term_method = at_module_exit
// default
default_term_method = at_binary_exit§default_unload_method
// default
default_unload_method = at_module_exit§export_name_prefix
#[cfg(target_os = "aix")]
export_name_prefix = "__sterm80000000"
// default
export_name_prefix = ()§link_section
#[cfg(target_vendor = "apple")]
link_section = "__DATA,__mod_term_func,mod_term_funcs"
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd",
target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly",
target_os = "illumos", target_os = "haiku", target_os = "vxworks", target_os =
"nto", target_family = "wasm"))]
link_section = ".fini_array"
#[cfg(target_os = "none")]
link_section = ".fini_array"
#[cfg(target_arch = "xtensa")]
link_section = ".dtors"
#[cfg(all(target_vendor = "pc", any(target_env = "gnu", target_env = "msvc")))]
link_section = ".CRT$XPU"
#[cfg(all(target_vendor = "pc", not(any(target_env = "gnu", target_env = "msvc"))))]
link_section = ".dtors"
#[cfg(all(target_os = "aix"))]
link_section = ()
// default
link_section = (compile_error! ("Unsupported target for #[dtor]"))§method
#[cfg(target_vendor = "apple")]
method = at_module_exit
#[cfg(target_vendor = "pc")]
method = at_module_exit
// default
method = linkerModules§
- declarative
- Declarative forms of the
#[dtor]macro.
Functions§
- at_
binary_ ⚠exit - Registers a raw function to be called at binary exit time.
- at_
module_ ⚠exit - Registers a raw function to be called at library (libc calls this a DSO or “dynamic shared object”) exit time.
Attribute Macros§
- dtor
- Marks a function as a library/executable destructor. This uses OS-specific linker sections to call a specific function at termination time.