vorner / signal-hook

Rust library allowing to register multiple handlers for the same signal

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

No EINTR anymore after signal_hook::low_level::register(SIGWINCH, ...)

gwenn opened this issue · comments

commented

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.

commented

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.

commented

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?

commented

Ok,
I will do like termwiz.
Thanks.