[Hands-on System Proframming with Linux]

可重入要求#

重入安全函数,一般叫 reentrant-safe ,在信号量处理语境下,叫 async-signal-safe .

async-signal-safe : invoking the function from within a signal handler while a previous invocation is still running is safe.

  • 安全的堆栈内存 由于信号量处理程序的重入、中断、等特性,在信号量处理程序中访问非堆栈内存时,需要考虑竞态问题。

As a general rule, functions that use only local variables are reentrant-safe; any usage of a global or a static data renders them unsafe. This is a key point: you can only call those functions in a signal handler that are documented as being reentrant-safe or signal-async-safe. The man page on signal-safety(7) http://man7.org/​linux/man-​pages/man7/signal-​safety.​7.html provides details for this.

So the bottom line is this: from within a signal handler, you can only invoke the following:

  • C library functions or system calls that are in the signal-safety(7) man page (do look it up)

  • Within a third-party library, functions explicitly documented as being async-signal-safe

  • Your own library or other functions that have been explicitly written to be async-signal-safe

Alternate ways to be safe within a signal handler#

What if we must access some global state within our signal handler routine? There do exist some alternate ways of making it signal-safe:

  • At the point you must access these variables, ensure that all signals are blocked (or masked), and, once done, restore the signal state (unmask).

  • Perform some kind of locking on shared data while accessing it.

    • In multiprocess applications (the case we are talking about here), (binary) semaphores can be used as a locking mechanism to protect shared data across processes.

    • In multithreaded applications, the use of an appropriate locking mechanism (mutex locks, perhaps; we shall, of course, cover this in a later chapter in detail).

  • If your requirement is to just operate upon global integers (a common case for signal handling!), use a special data type (the sig_atomic_t ). Seen later on.