No EINTR anymore after signal_hook::low_level::register(SIGWINCH, ...)
gwenn opened this issue · 5 comments
I am trying to switch from nix::sys::signal::sigaction
to signal_hook::low_level::register
here:
kkawakam/rustyline#608
Without signal-hook
, if I resize the terminal while the program is running:
$ RUST_LOG=rustyline=debug cargo run --example minimal
...
[DEBUG rustyline] SIGWINCH
[DEBUG rustyline] read error: Os { code: 4, kind: Interrupted, message: "Interrupted system call" }
...
An EINTR
occurs.
But with signal-hook
:
$ RUST_LOG=rustyline=debug cargo run --features signal-hook --example minimal
...
[DEBUG rustyline] SIGWINCH
...
There is no EINTR
anymore.
Could you please explain to me the difference between nix::sys::signal::sigaction
and signal_hook::low_level::register
?
Thanks.
Could be related to this line? https://github.com/vorner/signal-hook/blob/master/signal-hook-registry/src/lib.rs#L165
Can you show the code that needs the EINTR
? All the uses I've seen so far contained one kind of race condition or another.
The code that needs the EINTR is here:
https://github.com/gwenn/rustyline/blob/signal_hook/src/tty/unix.rs#L141
If a SIGWINCH event occurs while waiting for user input, an EINTR is caught and we repaint the line.
Could be related to this line? https://github.com/vorner/signal-hook/blob/master/signal-hook-registry/src/lib.rs#L165
That's it:
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -1132,7 +1132,7 @@ cfg_if::cfg_if! {
SIGWINCH_ONCE.call_once(|| unsafe {
let sigwinch = signal::SigAction::new(
signal::SigHandler::Handler(sigwinch_handler),
- signal::SaFlags::empty(),
+ signal::SaFlags::SA_RESTART,
signal::SigSet::empty(),
);
let _ = signal::sigaction(signal::SIGWINCH, &sigwinch);
nix::sys::signal::sigaction
behaves like signal_hook::low_level::register
if SA_RESTART
flag is activated.
Looking at the code, it is indeed subtly incorrect. If the SIGWINCH is delivered just before the read
, it won't get interrupted and will not get re-drawn.
Considering the SA_RESTART
behavior depends a lot on the given system and most code out there does handling of EINTR anyway, the flag could possibly be removed. Nevertheless, considering the above race, I'd suggest finding a better approach than this anyway. Maybe some variation of poll
or ppoll
in combination with the self-pipe trick?