Skip to content
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

Strange (?) interaction with SIGINT, cargo run, and stdin #5

Closed
birkenfeld opened this issue Feb 6, 2016 · 4 comments
Closed

Strange (?) interaction with SIGINT, cargo run, and stdin #5

birkenfeld opened this issue Feb 6, 2016 · 4 comments

Comments

@birkenfeld
Copy link

Not sure this is a chan-signal issue or a cargo/std::process issue.

Given the following code:

extern crate chan_signal;
use std::io::{stdin, stdout};
use std::io::Write;
use std::thread;
use std::sync::atomic::*;

pub static INTR: AtomicBool = ATOMIC_BOOL_INIT;

fn main() {
    let hchan = chan_signal::notify(&[chan_signal::Signal::INT]);
    thread::spawn(move || {
        if let Some(_) = hchan.recv() {
            INTR.store(true, Ordering::Relaxed);
        }
    });
    loop {
        if INTR.load(Ordering::Relaxed) {
            break;
        }
    }
    write!(stdout(), ">>> ");
    stdout().flush();
    let mut line = String::new();
    let input = stdin().read_line(&mut line);
    println!("Input: {:?} Result: {:?}", line, input);
}

it works fine when running the compiled binary on its own: loop happens, press Ctrl-C, prompt appears, line is read from stdin. When run with cargo run, reading the line fails with EIO.

@BurntSushi
Copy link
Owner

@birkenfeld Hmm, I'm not sure what's going on. Does cargo run do anything with signals? Maybe it closes stdin or something?

cc @alexcrichton

@alexcrichton
Copy link

I think this is basically expected behavior (unfortunately for now). What's happening is that the shell spawns a cargo process, which then in turn spawns the process for the program you listed above. When you hit ctrl-c the shell actually sends SIGINT to the process group of cargo rather than cargo itself, and this means that both cargo and the child process receive SIGINT. Cargo will then exit immediately (as it doesn't handle this), but the child process will handle it (as you've set it up to do).

The shell, however, will realize that Cargo has exited, and then I believe it will close the stdio pipes set up for that program (notably stdin). I think this happens because the shell owned the Cargo process (e.g. it's managing it after spawning it), so that is the process which basically decides if the subtree "lives or dies".

The two "fixes" for this that I know of are:

  • Run the process as the foreground shell (as you've already noted)
  • Change cargo to use exec so this sort of thing is set up correctly

To me at least this doesn't look like a bug in chan-signal, so hope that helps!

@BurntSushi
Copy link
Owner

@alexcrichton Thanks so much for that detailed analysis! I buy it. :-)

@birkenfeld
Copy link
Author

Thanks from me as well!

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

No branches or pull requests

3 participants