ghenry
September 10, 2024, 9:22am
1
Hi all,
I'm new to Tokio and have everything working that I'd like, but trying to shutdown gracefully. I'm using a oneshot::channel
to send a message to my Runtime to shutdown. Calling my shutdown routing from C. That's all working, but I think I'm fighting with my lack of Rust fundamentals.
I'm getting:
Cannot move
cannot move out of an `Arc` [E0507] move occurs because value has type `tokio::runtime::Runtime`, which does not implement the `Copy` trait Note: `tokio::runtime::Runtime::shutdown_background` takes ownership of the receiver `self`, which moves value
as I'm fighting with moves and saw Runtime in tokio::runtime - Rust
Here's my code:
// This runs the future on the tokio runtime
tokio::spawn(async move {
if fut.await != libc::EXIT_SUCCESS {
eprintln!("Failed to handle TLS connection");
}
});
}
});
match rx.await {
Ok(msg) => {
if debug_mode || verbose_mode {
eprintln!("Received message to shutdown: {:?}", msg);
}
// https://doc.rust-lang.org/nightly/alloc/sync/struct.Arc.html#method.into_inner
Arc::into_inner(rt_shutdown)
.unwrap()
.shutdown_background();
libc::EXIT_SUCCESS
}
The docs are great, and I was trying to use Cancellation Tokens too, but there's so much missing for a newbie to Tokio in places like // ... spawn application as separate task ...
and // send shutdown signal to application and wait
:
use tokio::signal;
use tokio::sync::mpsc;
#[tokio::main]
async fn main() {
let (shutdown_send, mut shutdown_recv) = mpsc::unbounded_channel();
// ... spawn application as separate task ...
//
// application uses shutdown_send in case a shutdown was issued from inside
// the application
tokio::select! {
_ = signal::ctrl_c() => {},
_ = shutdown_recv.recv() => {},
}
// send shutdown signal to application and wait
}
My full function is here, which needs a bit of tidy up:
libc::EXIT_SUCCESS
}
/// # Safety
///
/// Nothing is done with the `sentrypeer_config` pointer, it's treated read-only.
///
/// A default multi-threaded tokio runtime that listens for incoming TLS connections.
#[no_mangle]
pub(crate) extern "C" fn listen_tls(sentrypeer_c_config: *mut sentrypeer_config) -> i32 {
// Assert we're not getting a null pointer
assert!(!sentrypeer_c_config.is_null());
let rt = tokio::runtime::Builder::new_multi_thread()
.thread_name("tls_tokio_runtime")
.enable_all()
.build()
.unwrap();
let runtime = Arc::new(rt);
Maybe my next step is to create a tiny demo / reduced example.
Thanks.
ghenry
September 10, 2024, 7:44pm
2
Didn't need Arc
. Read the docs again and saw the fact I can do:
inner_runtime.shutdown_background();
All good now!
ghenry
September 10, 2024, 8:48pm
3
Hmm, looks like I'm creating two runtimes then:
(gdb) i thr
Id Target Id Frame
* 1 Thread 0x7ffff620abc0 (LWP 357235) "sentrypeer" 0x00007ffff76f2c13 in clock_nanosleep@GLIBC_2.2.5 () from /lib64/libc.so.6
2 Thread 0x7ffff58006c0 (LWP 357239) "MHD-listen" 0x00007ffff7727e57 in select () from /lib64/libc.so.6
3 Thread 0x7ffff4e006c0 (LWP 357240) "sip_daemon" 0x00007ffff7727e57 in select () from /lib64/libc.so.6
4 Thread 0x7ffff44006c0 (LWP 357241) "tls_tokio_runti" 0x00007ffff772aa32 in epoll_wait () from /lib64/libc.so.6
5 Thread 0x7fffefe006c0 (LWP 357242) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
6 Thread 0x7fffefa006c0 (LWP 357243) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
7 Thread 0x7fffef6006c0 (LWP 357244) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
8 Thread 0x7fffef2006c0 (LWP 357245) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
9 Thread 0x7fffeee006c0 (LWP 357246) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
10 Thread 0x7fffeea006c0 (LWP 357247) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
11 Thread 0x7fffee6006c0 (LWP 357248) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
12 Thread 0x7fffee2006c0 (LWP 357249) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
13 Thread 0x7fffede006c0 (LWP 357250) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
14 Thread 0x7fffeda006c0 (LWP 357251) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
15 Thread 0x7fffed6006c0 (LWP 357252) "tls_tokio_runti" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
16 Thread 0x7fffed2006c0 (LWP 357253) "tls_std_thread" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
17 Thread 0x7fffece006c0 (LWP 357254) "tokio-runtime-w" 0x00007ffff772aa32 in epoll_wait () from /lib64/libc.so.6
18 Thread 0x7fffeca006c0 (LWP 357255) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
19 Thread 0x7fffec6006c0 (LWP 357256) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
20 Thread 0x7fffe3e006c0 (LWP 357257) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
21 Thread 0x7fffe3a006c0 (LWP 357258) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
22 Thread 0x7fffe36006c0 (LWP 357259) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
23 Thread 0x7fffe32006c0 (LWP 357260) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
24 Thread 0x7fffe2e006c0 (LWP 357261) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
25 Thread 0x7fffe2a006c0 (LWP 357262) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
26 Thread 0x7fffe26006c0 (LWP 357263) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
27 Thread 0x7fffe22006c0 (LWP 357264) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
28 Thread 0x7fffe1e006c0 (LWP 357265) "tokio-runtime-w" 0x00007ffff77283dd in syscall () from /lib64/libc.so.6
ghenry
September 11, 2024, 4:29pm
4
So the solution for my future self, and others was to:
let rt = tokio::runtime::Builder::new_multi_thread()
.thread_name("tls_tokio_runtime")
.enable_all()
.build()
.unwrap();
let handle = rt.handle().clone();
then use that handle
instead of rt
:
let _std_thread_handle = thread_builder.spawn(move || {
handle.block_on(async move {
let config = config_from_env().unwrap();
then I can use rt
later as planned whilst listening for a oneshot
message to shutdown trigger by the other side of the FFI:
match rx.await {
Ok(msg) => {
if debug_mode || verbose_mode {
eprintln!("Tokio received a oneshot message to shutdown: {:?}", msg);
}
// https://docs.rs/tokio/latest/tokio/runtime/struct.Runtime.html#method.shutdown_background
rt.shutdown_background();
libc::EXIT_SUCCESS
}
Err(_) => {
eprintln!("Failed to receive message to shutdown.");
libc::EXIT_FAILURE
}
}
Full version here - SentryPeer/sentrypeer_rust/src/tls.rs at main · SentryPeer/SentryPeer · GitHub
2 Likes
system
Closed
December 10, 2024, 4:30pm
5
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.