Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is NotificationHandler::shutdown() really safe? #106

Open
HadrienG2 opened this issue Sep 3, 2019 · 2 comments
Open

Is NotificationHandler::shutdown() really safe? #106

HadrienG2 opened this issue Sep 3, 2019 · 2 comments

Comments

@HadrienG2
Copy link

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.

@wmedrano
Copy link
Member

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?

@HadrienG2
Copy link
Author

HadrienG2 commented Sep 15, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants