vorner / signal-hook

Rust library allowing to register multiple handlers for the same signal

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

FORBIDDEN doesn't make sense

jgarvin opened this issue · comments

  • I have to already know what Unix signals are
  • I have to decide that I then want to handle them and find the signal-hook crate
  • I have to read enough of the documentation to figure out how to register a handler
  • I have to write unsafe{ ... } in order to call register
  • And then I am blocked from registering a SIGSEGV handler anyway?

If the interface is already marked unsafe, who is being protected by this feature? It seems very unlikely to me that there is anyone who would have thought that registering a handler for SIGSEGV is a good idea, and got all the way to writing the unsafe block and running their code, but changed their mind after receiving the panic.

I would skip using the library altogether and just go to nix, but this library is the lingua franca in Rust for signal handling, and I give up being compatible with the central registry.

First, note that there is a version that allows you to do it: https://docs.rs/signal-hook-registry/1.3.0/signal_hook_registry/fn.register_unchecked.html.

Now as to who is protected and why this exists:

  • The idea is that independent parts of program can register multiple signals into the same handler and these will compose. This is probably not true for SIGSEGV and honestly, I haven't tried to document what the user needs to uphold for that to be safe.
  • After registering SIGSEGV, it now becomes unsafe to remove the handler, which isn't the case for the „normal“ signals.
  • There's a lot of additional helpers and abstractions built on top that are marked safe (by the crate and possibly by others). However, using them with SIGSEGV would certainly not be.

As the library and the documentation tries to explain, it is meant for kind of mainstream needs. Yes, if you need to handle SIGSEGV, you can either force this library or you can use nix directly ‒ you probably don't want the composition of signals there anyway. These signals and their semantics are very explicitly out of scope of what this library does.

SIGSEGV can compose. You can have a memory area that when it segfaults you mprotect it to make it writable/readable, provided it really faults on a location in that area. It's not crazy to have two such areas, and then chain two SIGSEGV handlers. Another useful thing something like signal-hook can handle is that the rust runtime already registers a SIGSEGV handler at startup to detect stack overflow. Users naively registering their own handler with nix without chaining the old one break this detection.

After registering SIGSEGV, it now becomes unsafe to remove the handler

Why?

There's a lot of additional helpers and abstractions built on top that are marked safe (by the crate and possibly by others). However, using them with SIGSEGV would certainly not be.

You can only get a SIGSEGV with unsafe code in the first place, so why would that code become any less safe? I don't see how SIGSEGV is any worse than any other signal?

Why?

The documentation is a bit sparse, but:

| According to POSIX, the behavior of a process is undefined after it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(2) or raise(3).

If the last action is removed from a handler, it doesn't restore SIG_DFL, but does nothing. That very much sounds like ignoring.

You can only get a SIGSEGV with unsafe code in the first place

No. You can absolutely do a stack overflow with completely safe code. That is only termination with SIGSEGV, not UB so far. You can also trigger SIGFPE, SIGILL in safe code…

The difference is that in these you have to remedy the situation before returning, or terminate. That's not the case with the other signals. And you have to do it inside the signal handler, not at some later point in time.

As said above, you can still use the unchecked versions. This panic is protecting all the safe abstractions that work by extracting the „signal happened“ somewhere outside from accidentally doing very nasty things. Anyway, removing the panic now would be a breaking change and it lives in the -registry which is 1.0.