'Initiating stop routine from thread in Rust from C++ code

Since this is most likely an XY problem, I will provide you with more background.

I am developing a library that starts a tokio::net::TcpListener, waits for incoming connections and processes them.

I have implemented a signal handler in a separate thread that catches SIGTERM/SIGINT and initiates a shutdown procedure:

tokio::select! {
    _ = sigterm.recv() => {
        println!("Received SIGTERM.");
    }
    _ = sigint.recv() => {
        println!("Received SIGINT.");
    }
};
// shutdown_server_tx.send(()) ....

When I build a binary instead of a library, run the application, and press CTRL+C, everything works as expected (signal catch and shutdown procedure are executed).

However, instead of building a standalone binary, I want to integrate my Rust code (as a lib) into existing C++ code. I have already created the pub extern "C" fn function and checked that I can correctly call it in C++. Obviously, when building the C++ code and starting the application, the signal is not passed onto my Rust code. This is a problem, because the shutdown routine implemented in Rust will not be executed.

I thought that I can address this issue by creating a tokio::sync::oneshot::channel() in my Rust application and add the receiver to the tokio::select! part. This definitely works, but the problem is that I do not know how to call the sender from C++.

This is what I tried:

lazy_static! {
    pub static ref SH_TX_RX: (Sender<()>, Receiver<()>) = oneshot::channel();
}

#[no_mangle]
pub extern "C" fn run() {
    
    println!("Starting server...");

    match srv::MyServer::new(SH_TX_RX.1) {
        Ok(server) => match server.run() {
            Ok(_) => {}
            Err(e) => {
                error!("Error: {:?}", e);
            }
        },
        Err(e) => {
            // ...
        }
    }

    println!("Exiting...");
}


#[no_mangle]
pub extern "C" fn exit() {
    let sender = &SH_TX_RX.0;
    sender.send(());
    ()
}

I thought that it needs to be static, because I cannot keep a pointer to MyServer in my C++ code. However, I get the following compiler errors:

error[E0507]: cannot move out of dereference of `SH_TX_RX`
  --> src/lib.rs:35:47
   |
35 |     match srv::MyServer::new(SHUTDOWN.1) {
   |                                               ^^^^^^^^^^ move occurs because value has type `tokio::sync::oneshot::Receiver<()>`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `*sender` which is behind a shared reference
  --> src/lib.rs:60:5
   |
60 |     sender.send(());
   |     ^^^^^^^^^^^^^^^ move occurs because `*sender` has type `tokio::sync::oneshot::Sender<()>`, which does not implement the `Copy` trait


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source