PROLOG | NAME | SYNOPSIS | DESCRIPTION | RETURN VALUE | ERRORS | EXAMPLES | APPLICATION USAGE | RATIONALE | FUTURE DIRECTIONS | SEE ALSO | COPYRIGHT

PTHREAD_ATFORK(3P)        POSIX Programmer's Manual       PTHREAD_ATFORK(3P)

PROLOG         top

       This manual page is part of the POSIX Programmer's Manual.  The Linux
       implementation of this interface may differ (consult the
       corresponding Linux manual page for details of Linux behavior), or
       the interface may not be implemented on Linux.

NAME         top

       pthread_atfork — register fork handlers

SYNOPSIS         top

       #include <pthread.h>

       int pthread_atfork(void (*prepare)(void), void (*parent)(void),
           void (*child)(void));

DESCRIPTION         top

       The pthread_atfork() function shall declare fork handlers to be
       called before and after fork(), in the context of the thread that
       called fork().  The prepare fork handler shall be called before
       fork() processing commences. The parent fork handle shall be called
       after fork() processing completes in the parent process. The child
       fork handler shall be called after fork() processing completes in the
       child process. If no handling is desired at one or more of these
       three points, the corresponding fork handler address(es) may be set
       to NULL.

       The order of calls to pthread_atfork() is significant. The parent and
       child fork handlers shall be called in the order in which they were
       established by calls to pthread_atfork().  The prepare fork handlers
       shall be called in the opposite order.

RETURN VALUE         top

       Upon successful completion, pthread_atfork() shall return a value of
       zero; otherwise, an error number shall be returned to indicate the
       error.

ERRORS         top

       The pthread_atfork() function shall fail if:

       ENOMEM Insufficient table space exists to record the fork handler
              addresses.

       The pthread_atfork() function shall not return an error code of
       [EINTR].

       The following sections are informative.

EXAMPLES         top

       None.

APPLICATION USAGE         top

       None.

RATIONALE         top

       There are at least two serious problems with the semantics of fork()
       in a multi-threaded program. One problem has to do with state (for
       example, memory) covered by mutexes. Consider the case where one
       thread has a mutex locked and the state covered by that mutex is
       inconsistent while another thread calls fork().  In the child, the
       mutex is in the locked state (locked by a nonexistent thread and thus
       can never be unlocked). Having the child simply reinitialize the
       mutex is unsatisfactory since this approach does not resolve the
       question about how to correct or otherwise deal with the inconsistent
       state in the child.

       It is suggested that programs that use fork() call an exec function
       very soon afterwards in the child process, thus resetting all states.
       In the meantime, only a short list of async-signal-safe library
       routines are promised to be available.

       Unfortunately, this solution does not address the needs of multi-
       threaded libraries. Application programs may not be aware that a
       multi-threaded library is in use, and they feel free to call any
       number of library routines between the fork() and exec calls, just as
       they always have. Indeed, they may be extant single-threaded programs
       and cannot, therefore, be expected to obey new restrictions imposed
       by the threads library.

       On the other hand, the multi-threaded library needs a way to protect
       its internal state during fork() in case it is re-entered later in
       the child process. The problem arises especially in multi-threaded
       I/O libraries, which are almost sure to be invoked between the fork()
       and exec calls to effect I/O redirection. The solution may require
       locking mutex variables during fork(), or it may entail simply
       resetting the state in the child after the fork() processing
       completes.

       The pthread_atfork() function was intended to provide multi-threaded
       libraries with a means to protect themselves from innocent
       application programs that call fork(), and to provide multi-threaded
       application programs with a standard mechanism for protecting
       themselves from fork() calls in a library routine or the application
       itself.

       The expected usage was that the prepare handler would acquire all
       mutex locks and the other two fork handlers would release them.

       For example, an application could have supplied a prepare routine
       that acquires the necessary mutexes the library maintains and
       supplied child and parent routines that release those mutexes, thus
       ensuring that the child would have got a consistent snapshot of the
       state of the library (and that no mutexes would have been left
       stranded). This is good in theory, but in reality not practical. Each
       and every mutex and lock in the process must be located and locked.
       Every component of a program including third-party components must
       participate and they must agree who is responsible for which mutex or
       lock. This is especially problematic for mutexes and locks in
       dynamically allocated memory. All mutexes and locks internal to the
       implementation must be locked, too. This possibly delays the thread
       calling fork() for a long time or even indefinitely since uses of
       these synchronization objects may not be under control of the
       application. A final problem to mention here is the problem of
       locking streams. At least the streams under control of the system
       (like stdin, stdout, stderr) must be protected by locking the stream
       with flockfile().  But the application itself could have done that,
       possibly in the same thread calling fork().  In this case, the
       process will deadlock.

       Alternatively, some libraries might have been able to supply just a
       child routine that reinitializes the mutexes in the library and all
       associated states to some known value (for example, what it was when
       the image was originally executed). This approach is not possible,
       though, because implementations are allowed to fail *_init() and
       *_destroy() calls for mutexes and locks if the mutex or lock is still
       locked. In this case, the child routine is not able to reinitialize
       the mutexes and locks.

       When fork() is called, only the calling thread is duplicated in the
       child process.  Synchronization variables remain in the same state in
       the child as they were in the parent at the time fork() was called.
       Thus, for example, mutex locks may be held by threads that no longer
       exist in the child process, and any associated states may be
       inconsistent. The intention was that the parent process could have
       avoided this by explicit code that acquires and releases locks
       critical to the child via pthread_atfork().  In addition, any
       critical threads would have needed to be recreated and reinitialized
       to the proper state in the child (also via pthread_atfork()).

       A higher-level package may acquire locks on its own data structures
       before invoking lower-level packages. Under this scenario, the order
       specified for fork handler calls allows a simple rule of
       initialization for avoiding package deadlock: a package initializes
       all packages on which it depends before it calls the pthread_atfork()
       function for itself.

       As explained, there is no suitable solution for functionality which
       requires non-atomic operations to be protected through mutexes and
       locks. This is why the POSIX.1 standard since the 1996 release
       requires that the child process after fork() in a multi-threaded
       process only calls async-signal-safe interfaces.

FUTURE DIRECTIONS         top

       None.

SEE ALSO         top

       atexit(3p), exec(1p), fork(3p)

       The Base Definitions volume of POSIX.1‐2008, pthread.h(0p),
       sys_types.h(0p)

COPYRIGHT         top

       Portions of this text are reprinted and reproduced in electronic form
       from IEEE Std 1003.1, 2013 Edition, Standard for Information
       Technology -- Portable Operating System Interface (POSIX), The Open
       Group Base Specifications Issue 7, Copyright (C) 2013 by the
       Institute of Electrical and Electronics Engineers, Inc and The Open
       Group.  (This is POSIX.1-2008 with the 2013 Technical Corrigendum 1
       applied.) In the event of any discrepancy between this version and
       the original IEEE and The Open Group Standard, the original IEEE and
       The Open Group Standard is the referee document. The original
       Standard can be obtained online at http://www.unix.org/online.html .

       Any typographical or formatting errors that appear in this page are
       most likely to have been introduced during the conversion of the
       source files to man page format. To report such errors, see
       https://www.kernel.org/doc/man-pages/reporting_bugs.html .

IEEE/The Open Group                 2013                  PTHREAD_ATFORK(3P)

Pages that refer to this page: pthread.h(0p)exec(3p)fork(3p)system(3p)