From 22d0780095b386c7ba64312cb9aae6ff23c52620 Mon Sep 17 00:00:00 2001 From: David Cook Date: Tue, 15 Oct 2019 20:37:02 -0500 Subject: [PATCH] Add failing test of log statement during TLS dtors --- Cargo.toml | 4 +++ tests/log_tls_dtors.rs | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/log_tls_dtors.rs diff --git a/Cargo.toml b/Cargo.toml index d040718..5dc1298 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,10 @@ harness = false name = "log-in-log" harness = false +[[test]] +name = "log_tls_dtors" +harness = false + [[test]] name = "init-twice-retains-filter" harness = false diff --git a/tests/log_tls_dtors.rs b/tests/log_tls_dtors.rs new file mode 100644 index 0000000..5db87bd --- /dev/null +++ b/tests/log_tls_dtors.rs @@ -0,0 +1,66 @@ +#[macro_use] +extern crate log; +extern crate env_logger; + +use std::env; +use std::process; +use std::str; +use std::thread; + +struct DropMe; + +impl Drop for DropMe { + fn drop(&mut self) { + debug!("Dropping now"); + } +} + +fn run() { + // Use multiple thread local values to increase the chance that our TLS + // value will get destroyed after the FORMATTER key in the library + thread_local! { + static DROP_ME_0: DropMe = DropMe; + static DROP_ME_1: DropMe = DropMe; + static DROP_ME_2: DropMe = DropMe; + static DROP_ME_3: DropMe = DropMe; + static DROP_ME_4: DropMe = DropMe; + static DROP_ME_5: DropMe = DropMe; + static DROP_ME_6: DropMe = DropMe; + static DROP_ME_7: DropMe = DropMe; + static DROP_ME_8: DropMe = DropMe; + static DROP_ME_9: DropMe = DropMe; + } + DROP_ME_0.with(|_| {}); + DROP_ME_1.with(|_| {}); + DROP_ME_2.with(|_| {}); + DROP_ME_3.with(|_| {}); + DROP_ME_4.with(|_| {}); + DROP_ME_5.with(|_| {}); + DROP_ME_6.with(|_| {}); + DROP_ME_7.with(|_| {}); + DROP_ME_8.with(|_| {}); + DROP_ME_9.with(|_| {}); +} + +fn main() { + env_logger::init(); + if env::var("YOU_ARE_TESTING_NOW").is_ok() { + // Run on a separate thread because TLS values on the main thread + // won't have their destructors run if pthread is used. + // https://doc.rust-lang.org/std/thread/struct.LocalKey.html#platform-specific-behavior + thread::spawn(run).join().unwrap(); + } else { + let exe = env::current_exe().unwrap(); + let out = process::Command::new(exe) + .env("YOU_ARE_TESTING_NOW", "1") + .env("RUST_LOG", "debug") + .output() + .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); + if !out.status.success() { + println!("test failed: {}", out.status); + println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); + println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); + process::exit(1); + } + } +}