Yolinux.com

pthread_atfork manpage

Search topic Section


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



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()  pro-
       cessing	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
       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
       None.

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 exam-
       ple, 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  unsatis-
       factory	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  rou-
       tines 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 problem-
       atic for mutexes and locks in dynamically allocated memory. All mutexes
       and locks internal to the implementation must be locked, too. This pos-
       sibly  delays the thread calling fork() for a long time or even indefi-
       nitely 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 inconsis-
       tent. 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
       None.

SEE ALSO
       atexit(), exec, fork()

       The Base Definitions volume of POSIX.1-2008, <pthread.h>, <sys_types.h>

COPYRIGHT
       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 Electri-
       cal  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.ker-
       nel.org/doc/man-pages/reporting_bugs.html .



IEEE/The Open Group		     2013		    PTHREAD_ATFORK(3P)