Using the fork function in signal handlers
The GNU C Library (shipped as part of Red Hat Enterprise Linux in the glibc
) package provides a function called fork
, which creates a new process as a copy of the current process image.
POSIX specifies that fork
can be called safely from signal handlers; it is required to be an async-signal-safe function. However, the implementation in glibc does not match this requirement. The main reason is that existing application usage requires that memory allocation functions such as malloc
and free
must work in the new subprocess created by fork
, even in the case where the original process was multi-threaded. Therefore, fork
must bring the original process into a consistent state as far as malloc
is concerned, and in general, this is not possible when fork
is executed from a signal handler. The current implementation may self-deadlock under such circumstances and the process invoking fork
will hang indefinitely.
There is an upstream bug which tracks this POSIX compliance issue:
The downstream bug for Red Hat Enterprise Linux is:
As of February 2017, this issue has only been addressed partially upstream (for single-threaded programs in glibc 2.25).
Even though POSIX permits calls to fork
from signal handlers, it is unclear what happens if a function which is not async-signal-safe is called from a fork handler (registered using pthread_atfork
). The general interpretation is that if fork
is called from a signal handler, all registered signal handlers must only call async-signal-safe functions. Furthermore, the consensus interpretation is that after a fork
from a signal handler, the new subprocess essentially remains in a signal handler context and must call async-signal-safe functions only.
Future versions of POSIX may drop the requirement for fork
to be async-signal-safe, so it is recommended to adjust applications not to call fork
from signal handlers. In particular, applications should use system crash handlers such as abrt
instead of installing signal handlers which use fork
as part of an attempt to write a coredump. An out-of-process crash handler preserves more process information (such as register and stack contents at the time of the crash) compared to an in-process crash handler because the crash handler itself overwrites information.
Historically, there have been other reasons why the fork
function can deadlock and hang indefinitely. These issues may be addressed as part of the regular maintenance of the glibc
package in Red Hat Enterprise Linux.
Comments