I'm writing a shell in rust and I'm trying to make my shell not exit if I ^C a program the started.
I'm starting the child process with this code. The readline library I'm using, rustyline, typically handles exit signals but if ^C is press while a program is running the shell exits. Any ideas on how to prevent this?
match Command::new(&args[0])
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn() {
Ok(mut cmd) => {
match cmd.wait() {
Ok(status) => {
status.success()
},
Err(_) => {
println!("failed to wait for child");
false
},
}
},
Err(_) => {
println!("Failed to execute");
false
},
}
I can't give you many Rust specifics except that you'll have to stop using spawn and switch to POSIX API. Here's a discussion of doing it in C, which should mostly translate.
Actually, you should be able to do this using Command::spawn. What you have to do is create the new process group in a before_exec hook. This method is added by the CommandExt trait only available on unix.
In the before_exec callback, you'll need to use the C functions to actually create a new process group. These are available through the libc crate.
Nice. Is that hook executed synchronously before spawn returns? (The documentation implies this but doesn't state it explicitly.)
If that's the case, you can likely avoid the double-process-group-setting trick that we usually do in C to avoid certain race conditions. The Wikipedia page notes that handling the process group transition synchronously (i.e. by writing to a pipe after it's complete) can avoid the race... you'd want to be careful though.
Since failures in the hook are conveyed back to the parent process, it seems like it must be creating a pipe and pushing the result back -- which would mean it's synchronous, and could avoid the race condition in setpgid. But I should probably try it out.
It would seem that I also need to execute the tcsetpgrp function to put the child process in the foreground but I can't find a rust binding for it. Anyone know of one? posix.rs is no longer mainted and nix doesn't seem to have it.