Skip to content

fix(sync): Avoid panic when using sync client from a GCC destructor #308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

papazof
Copy link
Contributor

@papazof papazof commented Jul 16, 2025

Calling Rust from a GCC destructor can result in panics when using pthreads (rust-lang/rust-28129). Move client request code to a separate thread to work around this issue.

Calling Rust from a GCC destructor can result in panics when using
pthreads (rust-lang/rust-28129). Move client request code to a separate
thread to work around this issue.

Signed-off-by: Kostis Papazafeiropoulos <[email protected]>
@papazof papazof marked this pull request as ready for review July 16, 2025 19:30
@Tim-Zhang
Copy link
Member

Tim-Zhang commented Jul 31, 2025

Hi @papazof, Could you give more information especially about how "Dtors may not run" problem affect these code. Thank you

@papazof
Copy link
Contributor Author

papazof commented Jul 31, 2025

Sure. There are cases where we make RPC requests using the ttrpc client from a GCC destructor - ie. making ttrpc client requests from a C function marked with __attribute__((destructor)). Such usage consistently results in panics like:

thread '<unnamed>' panicked at library/std/src/thread/mod.rs:769:19:
use of std::thread::current() is not possible after the thread's local data has been destroyed
stack backtrace:                                         
   0: rust_begin_unwind              
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5                                                                                                                                             
   1: core::panicking::panic_fmt                                                                                       
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14
   2: core::panicking::panic_display             
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:264:5
   3: core::option::expect_failed
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:2030:5
   4: core::option::Option<T>::expect
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:933:21
   5: std::thread::current
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/thread/mod.rs:769:19
   6: std::sync::mpmc::context::Context::new
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/mpmc/context.rs:73:25
   7: std::sync::mpmc::context::Context::with::{{closure}}
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/mpmc/context.rs:63:36
   8: core::result::Result<T,E>::unwrap_or_else
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:1456:23
   9: std::sync::mpmc::context::Context::with
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/mpmc/context.rs:63:14
  10: std::sync::mpmc::zero::Channel<T>::recv
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/mpmc/zero.rs:256:9
  11: std::sync::mpmc::Receiver<T>::recv
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/mpmc/mod.rs:308:43
  12: std::sync::mpsc::Receiver<T>::recv
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/sync/mpsc/mod.rs:849:9
  13: ttrpc::sync::client::Client::request
             at /home/papazof/.cargo/git/checkouts/ttrpc-rust-f4052649e2b990ed/f31f592/src/sync/client.rs:173:13
  14: vaccel_rpc_proto::sync::agent_ttrpc::AgentServiceClient::destroy_session
             at ./subprojects/vaccel-rust/cargo_target/debug/build/vaccel-rpc-proto-e6ae16900afe98cc/out/sync/agent_ttrpc.rs:47:9
  15: core::ops::function::Fn::call
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:79:5
  16: vaccel_rpc_client::sync::client::VaccelRpcClient::execute
             at /home/papazof/vaccel-plugin-rpc_/subprojects/vaccel-rust/vaccel-rpc-client/src/sync/client.rs:34:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

@Tim-Zhang
Copy link
Member

Tim-Zhang commented Aug 1, 2025

image I got a sequence image from asking a LLM, it says that when __attribute__((destructor)) functions execute, Rust's TLS data has already been destroyed, so I figure it is a usage problem not ttrpc's bug.

How about trying to call a the Client::request inside atexit?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants