I came across something similar to this in a library and it seems like it's causing Rust to panic at the very end of my program. I stripped out most of the irrelevant code, and this seems to be the minimal example needed to reproduce it.
It seems like this code pretty closely follows the documented use of std::thread_local and with. Is there some kind of destruction going on here that reqwest::blocking::Client doesn't support properly? Or is there some cleanup I'm supposed to do before exiting?
use reqwest::blocking::Client;
std::thread_local!(static CLIENT: Client = Client::new());
fn main() {
match CLIENT.with(|c| {c.get("https://www.rust-lang.org").send()}) {
Ok(_) => {
println!("success!");
},
Err(_) => {
println!("error!");
}
}
}
Here's the error I'm getting:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Running `target\debug\example.exe`
success!
thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\std\src\thread\mod.rs:1245:48
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
If I avoid using thread_local and just initialize a regular local variable it works fine:
use reqwest::blocking::Client;
fn main() {
let client: Client = Client::new();
match client.get("https://www.rust-lang.org").send() {
Ok(_) => {
println!("success!");
},
Err(_) => {
println!("error!");
}
}
}
I'm running on Windows 10 with rustc 1.49.0 (e1884a8e3 2020-12-29)
My cargo.toml has reqwest = { version = "0.10", features = ["blocking"] }
If I run with full backtrace I get the following output
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.16s
Running `target\debug\example.exe`
success!
thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\std\src\thread\mod.rs:1245:48
stack backtrace:
0: 0x7ff6f376f54e - std::backtrace_rs::backtrace::dbghelp::trace
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\..\..\backtrace\src\backtrace\dbghelp.rs:108
1: 0x7ff6f376f54e - std::backtrace_rs::backtrace::trace_unsynchronized
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\..\..\backtrace\src\backtrace\mod.rs:66
2: 0x7ff6f376f54e - std::sys_common::backtrace::_print_fmt
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys_common\backtrace.rs:67
3: 0x7ff6f376f54e - std::sys_common::backtrace::_print::{{impl}}::fmt
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys_common\backtrace.rs:46
4: 0x7ff6f37844eb - core::fmt::write
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\core\src\fmt\mod.rs:1078
5: 0x7ff6f3768d58 - std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\io\mod.rs:1518
6: 0x7ff6f37720dd - std::sys_common::backtrace::_print
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys_common\backtrace.rs:49
7: 0x7ff6f37720dd - std::sys_common::backtrace::print
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys_common\backtrace.rs:36
8: 0x7ff6f37720dd - std::panicking::default_hook::{{closure}}
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\panicking.rs:208
9: 0x7ff6f3771cb8 - std::panicking::default_hook
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\panicking.rs:227
10: 0x7ff6f3772a4f - std::panicking::rust_panic_with_hook
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\panicking.rs:593
11: 0x7ff6f3772523 - std::panicking::begin_panic_handler::{{closure}}
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\panicking.rs:497
12: 0x7ff6f376fe8f - std::sys_common::backtrace::__rust_end_short_backtrace<closure-0,!>
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys_common\backtrace.rs:141
13: 0x7ff6f37724a9 - std::panicking::begin_panic_handler
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\panicking.rs:495
14: 0x7ff6f3782a60 - core::panicking::panic_fmt
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\core\src\panicking.rs:92
15: 0x7ff6f37829ac - core::panicking::panic
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\core\src\panicking.rs:50
16: 0x7ff6f363a940 - core::option::Option<core::result::Result<tuple<>, alloc::boxed::Box<Any, alloc::alloc::Global>>>::unwrap<core::result::Result<tuple<>, alloc::boxed::Box<Any, alloc::alloc::Global>>>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\option.rs:386
17: 0x7ff6f36169bb - std::thread::JoinInner<tuple<>>::join<tuple<>>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\thread\mod.rs:1245
18: 0x7ff6f36169fb - std::thread::JoinHandle<tuple<>>::join<tuple<>>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\thread\mod.rs:1373
19: 0x7ff6f32bfac1 - reqwest::blocking::client::{{impl}}::drop::{{closure}}
at C:\Users\rober\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.10\src\blocking\client.rs:752
20: 0x7ff6f32dcde9 - core::option::Option<std::thread::JoinHandle<tuple<>>>::map<std::thread::JoinHandle<tuple<>>,core::result::Result<tuple<>, alloc::boxed::Box<Any, alloc::alloc::Global>>,closure-1>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\option.rs:453
21: 0x7ff6f32bf8e1 - reqwest::blocking::client::{{impl}}::drop
at C:\Users\rober\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.10\src\blocking\client.rs:752
22: 0x7ff6f32d723f - core::ptr::drop_in_place<reqwest::blocking::client::InnerClientHandle>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:175
23: 0x7ff6f32e4832 - alloc::sync::Arc<reqwest::blocking::client::InnerClientHandle>::drop_slow<reqwest::blocking::client::InnerClientHandle>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\sync.rs:951
24: 0x7ff6f32e84a0 - alloc::sync::{{impl}}::drop<reqwest::blocking::client::InnerClientHandle>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\sync.rs:1471
25: 0x7ff6f32cee8e - core::ptr::drop_in_place<alloc::sync::Arc<reqwest::blocking::client::InnerClientHandle>>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:175
26: 0x7ff6f32cb1f5 - core::ptr::drop_in_place<reqwest::blocking::client::ClientHandle>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:175
27: 0x7ff6f32d6afe - core::ptr::drop_in_place<reqwest::blocking::client::Client>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:175
28: 0x7ff6f32a22b2 - core::ptr::drop_in_place<core::option::Option<reqwest::blocking::client::Client>>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:175
29: 0x7ff6f32a1c09 - core::mem::drop<core::option::Option<reqwest::blocking::client::Client>>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\mem\mod.rs:882
30: 0x7ff6f32a2ae2 - std::thread::local::fast::destroy_value<reqwest::blocking::client::Client>
at C:\Users\rober\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\thread\local.rs:519
31: 0x7ff6f3770b4b - std::sys_common::thread_local_dtor::register_dtor_fallback::run_dtors
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys_common\thread_local_dtor.rs:43
32: 0x7ff6f3775e58 - std::sys::windows::thread_local_key::run_dtors
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys\windows\thread_local_key.rs:245
33: 0x7ff6f3775e58 - std::sys::windows::thread_local_key::on_tls_callback
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca\/library\std\src\sys\windows\thread_local_key.rs:214
34: 0x7ffa829a5021 - RtlActivateActivationContextUnsafeFast
35: 0x7ffa829a5103 - RtlActivateActivationContextUnsafeFast
36: 0x7ffa829eb1b0 - LdrShutdownProcess
37: 0x7ffa829eafad - RtlExitUserProcess
38: 0x7ffa8289cdda - ExitProcess
39: 0x7ffa8019ae58 - o_free
40: 0x7ffa8019870f - exit
41: 0x7ff6f378aaf7 - __scrt_common_main_seh
at d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:295
42: 0x7ffa82897c24 - BaseThreadInitThunk
43: 0x7ffa829ed4d1 - RtlUserThreadStart
It does seem like it has something to do with a destructor of some kind, I see reqwest::blocking::client::{{impl}}::drop in the full stacktrace, but I don't really know enough about Rust to form a more complete theory of what's going on here.