Provided by: manpages-posix-dev_2017a-2_all bug

PROLOG

       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

       pthread_atfork — register fork handlers

SYNOPSIS

       #include <pthread.h>

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

DESCRIPTION

       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.

       If a fork() call in a multi-threaded process leads to a child fork handler calling any function  that  is
       not async-signal-safe, the behavior is undefined.

       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

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

ERRORS

       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

       None.

APPLICATION USAGE

       The  original  usage  pattern  envisaged  for  pthread_atfork()  was for the prepare fork handler to lock
       mutexes and other locks, and for the parent and child handlers to unlock them. However, since all of  the
       relevant  unlocking  functions,  except  sem_post(),  are  not  async-signal-safe,  this usage results in
       undefined behavior in the child process unless the only such unlocking function it calls is sem_post().

RATIONALE

       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

       The  pthread_atfork()  function  may  be  formally deprecated (for example, by shading it OB) in a future
       version of this standard.

SEE ALSO

       atexit(), exec, fork()

       The Base Definitions volume of POSIX.1‐2017, <pthread.h>, <sys_types.h>

COPYRIGHT

       Portions of this text are reprinted and reproduced in electronic form from IEEE Std 1003.1-2017, Standard
       for Information  Technology  --  Portable  Operating  System  Interface  (POSIX),  The  Open  Group  Base
       Specifications  Issue  7, 2018 Edition, Copyright (C) 2018 by the Institute of Electrical and Electronics
       Engineers, Inc and The Open Group.  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.opengroup.org/unix/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                                   2017                                PTHREAD_ATFORK(3POSIX)