-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Allow waiting for the process multiple times #3790
Comments
Hey. Please help. Currently I am trying to implement async version of nix::sys::ptrace::syscall(pid, None).unwrap(); // This sends SIGCHLD
let kind = tokio::signal::unix::SignalKind::child();
let mut signal = tokio::signal::unix::signal(kind).unwrap();
signal.recv().await; // endless awaiting
// This won't be executed.
|
Maybe you are hitting race condition? I think it is possible that kernel delivers |
I tried to set the following code at the start of the program but it prints only "Awaiting SIGCHLD" tokio::spawn(async {
let kind = tokio::signal::unix::SignalKind::child();
loop {
let mut signal = tokio::signal::unix::signal(kind).unwrap();
println!("Awaiting SIGCHLD");
signal.recv().await;
println!("Got SIGCHLD");
}
}); |
Look at this code: use std::os::unix::process::CommandExt;
use nix::sys::{wait, ptrace};
#[tokio::main]
async fn main() -> std::io::Result<()> {
// This handles only exit SIGCHLD signal
tokio::spawn(async {
let kind = tokio::signal::unix::SignalKind::child();
loop {
let mut signal = tokio::signal::unix::signal(kind).unwrap();
println!("Awaiting SIGCHLD");
signal.recv().await;
println!("Got SIGCHLD");
}
});
// This handles all SIGCHLD signals
// let handler = nix::sys::signal::SigHandler::Handler(handle_signal);
// unsafe {
// nix::sys::signal::signal(nix::sys::signal::SIGCHLD, handler).unwrap();
// }
run_command().await;
println!("Bye");
Ok(())
}
extern fn handle_signal(signal: i32) {
println!("Signal {}", signal);
}
async fn run_command() {
// libc::raise(libc::SIGCHLD);
let mut command = std::process::Command::new("ls");
unsafe {
command.pre_exec(start_traceme);
}
let child = command.spawn().unwrap();
let pid = nix::unistd::Pid::from_raw(child.id() as _);
wait::waitpid(pid, None).unwrap();
ptrace::setoptions(pid, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
loop {
ptrace::syscall(pid, None).unwrap();
// tokio::task::yield_now().await;
wait::waitpid(pid, None).unwrap();
let state = ptrace::getregs(pid).unwrap();
println!("SYSCALL {}", state.orig_rax);
ptrace::syscall(pid, None).unwrap();
let status = wait::waitpid(pid, None).unwrap();
if let wait::WaitStatus::Exited(_, code) = status {
println!("Exit {}", code);
return
}
}
}
fn start_traceme() -> std::io::Result<()> {
ptrace::traceme().map_err(|err| {
let kind = std::io::ErrorKind::Other;
std::io::Error::new(kind, err)
})
} |
@VictorBulba tokio signal handlers are registered lazily, so if the signal handler is registered after the command is spawned, it's entirely possible the OS will deliver the signal before the code to register the handler has actually run. Could you try registering a tokio signal listener first before spawning a command? |
Responding to the original message:
The tokio child process implementation delegates to the standard library which does cache exit results. I'm not against some kind of API which allows for getting non-exit child statuses, but it will need to be a new API since changing the semantics of the existing APIs can be considered a breaking change (and surprising behavior compared to what std does). FWIW it seems like there are some nightly APIs for checking if a child was stopped: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.stopped_signal (tracked in rust-lang/rust#80695 ) |
Look at the code above, it spawns a task that starts awaiting for the SIGCHLD before the command starts. |
Yeah, with nightly api it is possible to convert exit status |
I'm closing this because I opened a new one with a similar problem #3804 |
I am trying to use ptrace for tracing processes created with tokio
Command
. I need to wait for the process multiple times. Butwait
is guaranteed to return same cached status. I would like to have an async api that makewaitpid
every time it is called.The text was updated successfully, but these errors were encountered: