What constitutes asynchronous-safeness
Asked Answered
G

2

15

It is said that you should only call asynchronous-safe functions inside a signal handler. My question is, what constitutes asynchronous-safeness? A function which is both reentrant and thread safe is asynchronous-safe I guess? Or No?

Glavin answered 13/12, 2011 at 17:0 Comment(2)
Found this. So it seems that function may not use global variables (beside atomic types) and interrupting it at any point should leave the process in consistent state.Kay
I'd say reentrant and not accessing thread local stuff. If you access thread local stuff you'll be competing with the thread you'll be interrupting and possibly cause data corruption.Behead
L
14

Re-entrance and thread safety has a little or nothing to do with this. Side effects, state and interruption of those functions are facts that matter.

asynchronous-safe function [GNU Pth]

A function is asynchronous-safe, or asynchronous-signal safe, if it can be called safely and without side effects from within a signal handler context. That is, it must be able to be interrupted at any point to run linearly out of sequence without causing an inconsistent state. It must also function properly when global data might itself be in an inconsistent state. Some asynchronous-safe operations are listed here:

  • call the signal() function to reinstall a signal handler
  • unconditionally modify a volatile sig_atomic_t variable (as modification to this type is atomic)
  • call the _Exit() function to immediately terminate program execution
  • invoke an asynchronous-safe function, as specified by your implementation

Few functions are portably asynchronous-safe. If a function performs any other operations, it is probably not portably asynchronous-safe.

A rule of thumb is this - only signal some condition variable from signal handler (such as futex/pthread condition, wake up epoll loop etc.).

UPDATE:

As EmployedRussian suggested, even calling pthread_cond_signal is a bad idea. I've checked the source code of the recent eglibc and it has lock/unlock pair in there. Thus, introducing a possibility for a deadlock. This leaves us with few options to signal other threads:

  1. Using eventfd.
  2. Changing global atomic variable and hope that SA_RESTART is not set and other threads will check our atomic.
Ligate answered 13/12, 2011 at 17:4 Comment(6)
There is a much larger list of functions that are guaranteed to be async-signal-safe by POSIX.1-2008 (you'll have to scroll down a bit for the list), including the majority of traditional-Unix "system calls," and access to errno. Also, if you know that your signal handlers will only be called when normal execution is blocked on sigsuspend, then it's safe to do arbitrary stuff in the handler.Dang
None of pthread_* functions are async-signal-safe, so "signal pthread condition variable" is a bad advice (TM).Greasewood
@EmployedRussian: Not that it is not safe, it might just not wake up someone waiting on a POSIX condition variable.Ligate
@EmployedRussian: Actually, I take my words back - just checked the source code and it may as well lead to deadlock :-) So I guess the only safe wakeup is trough fcntl and/or atomic variable.Ligate
The usual trick for waking up a select-style main loop from a signal handler is to write a byte to a pipe that is in the fds-of-interest set. signalfd may also be of interest.Dang
sem_post() is async-signal-safe, making it perfect for signaling a thread waiting in sem_wait().Golfer
C
1

For your own code, yes, re-entrant and thread-safe are the characteristics you need, as, depending on how you set up your signal handling mechanism, your signal handler may itself be interrupted by another signal. In general, try to do as little work as possible inside the signal handler. Setting flags to trigger special code in your normal program flow is probably all you should be doing.

For functions in the OS that you might call, check out man 7 signal for a list of what is safe to call. Note that malloc() and free() are not on the list. The pthread synchronization APIs are not on the list either, but I would think that some would have to be safe to call, so you can set a global flag safely in a signal handler.

Cosgrove answered 13/12, 2011 at 17:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.