Open eldoccc opened 2 months ago
Did you try: https://docs.rs/rustyline/latest/rustyline/config/struct.Config.html#method.enable_signals or this: https://man7.org/linux/man-pages/man3/termios.3.html
c_iflag flag constants:
IGNBRK Ignore BREAK condition on input. BRKINT If IGNBRK is set, a BREAK is ignored. If it is not set but BRKINT is set, then a BREAK causes the input and output queues to be flushed, and if the terminal is the controlling terminal of a foreground process group, it will cause a SIGINT to be sent to this foreground process group. When neither IGNBRK nor BRKINT are set, a BREAK reads as a null byte ('\0')
? https://github.com/search?q=repo%3Akkawakam%2Frustyline%20BRKINT&type=code
isn't this for recognizing signal input on stdin ? I might've explained myself poorly.
Currently, rustyline never yields, and remains ''stuck'' on waiting for input, what I'd like rustyline to do, is to listen for signals coming from another thread / task, something as simple as nix::sys::signal::kill(nix::unistd::getpid(), nix::sys::signal::SIGINT)
.
Yes, calling a SIGINT already closes the process, but it's brutal and it'd be better if rustyline could exit its loop properly.
with that in mind, this idea could be expanded to other signals.
Ok, ISIG
:
use std::thread;
use std::time::Duration;
use rustyline::{Config, DefaultEditor, Result};
fn main() -> Result<()> {
env_logger::init();
let config = Config::builder().enable_signals(true).build();
let mut rl = DefaultEditor::with_config(config)?;
thread::spawn(|| {
thread::sleep(Duration::from_secs(5));
unsafe { libc::raise(libc::SIGINT) }
});
loop {
let result = rl.readline("> ");
match result {
Ok(line) => {
println!("Line: {line}");
}
Err(err) => {
println!("Err: {err:?}");
break Err(err);
}
}
}
}
rustyline % RUST_LOG=rustyline=debug cargo run --example signal
doesn't work. https://stackoverflow.com/a/75704077/21836177
Finally, it may be worth mentioning that this only disables the special characters used to generate the corresponding signals, the signals can still be sent using the kill function.
So enable_signals
seems useless (at least in your case).
And while trying to rewrite this code in Rust:
https://github.com/daanx/isocline/blob/c9310ae58941559d761fe5d2dd2713d245f18da6/src/tty.c#L581-L626
It appears that with signal_hook
, if you use the same pipe for different signals, you cannot distinguish which signal is received:
use std::io::{Error, Read};
use std::os::unix::net::UnixStream;
use signal_hook::consts::{SIGUSR1, SIGUSR2};
use signal_hook::low_level::{pipe, raise};
fn main() -> Result<(), Error> {
let (mut read, write) = UnixStream::pair()?;
pipe::register(SIGUSR1, write.try_clone()?)?;
pipe::register(SIGUSR2, write)?;
let signal = SIGUSR2;
raise(signal).unwrap();
let mut buff = [0];
read.read_exact(&mut buff)?;
println!("buff: {buff:?} / {signal}");
Ok(())
}
https://docs.rs/signal-hook/latest/signal_hook/low_level/pipe/index.html
the signal handler writes one byte of garbage data to the write end
Hi, I was wondering if the rustyline team was interested for help concerning signal handling ? Currently, rustlyline only listens to SIGWINCH and it would be nice to have at least SIGINT, (that would solve #780).
I was thinking in doing it in similar way to linefeed where you specify a list of signals you'd want to listen (my main personnal need would be for SIGINT).
If so, would you be kind to indicate which approach would fit your philosophy better :
ATM, I've done quick modifications just to listen to another signal of your choice here.
thanks !