rust-jack icon indicating copy to clipboard operation
rust-jack copied to clipboard

Is NotificationHandler::shutdown() really safe?

Open HadrienG2 opened this issue 4 years ago • 2 comments

If it truly acts like a POSIX signal handler, then it exposes a bewildering range of avenues for undefined behavior and should definitely be an unsafe fn.

HadrienG2 avatar Sep 03 '19 21:09 HadrienG2

I'm not too familiar with POSIX signal handling. Can you give some details on what programmers are expected to do/notDo in NotificationHandler::shutdown?

wmedrano avatar Sep 14 '19 23:09 wmedrano

Asynchronous POSIX signals (sorry, I forgot the qualifier, it's important) basically behave like hardware interrupts. Whenever your OS feels like it, it can take one of your threads and have it call a signal handling rountine, without waiting for that thread to finish whatever it was doing first. In fact, this can occur even if that thread was already in the process of running such a signal handling routine.

The thread that is running a signal handler can therefore see its data in a very awkward state, where objects in memory can be half-written (because it was in the process of writing them), mutexes are potentially taken (because it was holding one), and so on... in effect, it is very much as if it were a different thread doing racey data accesses, but with two important differences:

  • Since it's the same thread, some usual mitigations against data races like thread-local storage are defeated, and the thread can race against itself (!) through that mean. This is important because TLS is intensively used, both by the libc and Rust's std library, and there is no way to distinguish a function that uses TLS from one that doesn't from API alone.
  • Anything that involves a lock is super-dangerous, because it is easy to end up in a deadlock situation where the thread waits for itself to release the lock in the signal handler, but would not do so until the signal handler finishes and normal work (or another signal handler lower in the call stack) resumes. For this reason, it is generally recommended to only use lock-free synchronization in signal handlers.

As you can see, it's a very tricky programming model that breaks Rust's normal safety invariants and is easy to get wrong. This is why I think unsafe is warranted here.

HadrienG2 avatar Sep 15 '19 02:09 HadrienG2