Blame man-pages-posix-2013-a/man3p/pthread_atfork.3p

Packit 7cfc04
'\" et
Packit 7cfc04
.TH PTHREAD_ATFORK "3P" 2013 "IEEE/The Open Group" "POSIX Programmer's Manual"
Packit 7cfc04
.SH PROLOG
Packit 7cfc04
This manual page is part of the POSIX Programmer's Manual.
Packit 7cfc04
The Linux implementation of this interface may differ (consult
Packit 7cfc04
the corresponding Linux manual page for details of Linux behavior),
Packit 7cfc04
or the interface may not be implemented on Linux.
Packit 7cfc04
Packit 7cfc04
.SH NAME
Packit 7cfc04
pthread_atfork
Packit 7cfc04
\(em register fork handlers
Packit 7cfc04
.SH SYNOPSIS
Packit 7cfc04
.LP
Packit 7cfc04
.nf
Packit 7cfc04
#include <pthread.h>
Packit 7cfc04
.P
Packit 7cfc04
int pthread_atfork(void (*\fIprepare\fP)(void), void (*\fIparent\fP)(void),
Packit 7cfc04
    void (*\fIchild\fP)(void));
Packit 7cfc04
.fi
Packit 7cfc04
.SH DESCRIPTION
Packit 7cfc04
The
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
function shall declare fork handlers to be called before and after
Packit 7cfc04
\fIfork\fR(),
Packit 7cfc04
in the context of the thread that called
Packit 7cfc04
\fIfork\fR().
Packit 7cfc04
The
Packit 7cfc04
.IR prepare
Packit 7cfc04
fork handler shall be called before
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
processing commences. The
Packit 7cfc04
.IR parent
Packit 7cfc04
fork handle shall be called after
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
processing completes in the parent process. The
Packit 7cfc04
.IR child
Packit 7cfc04
fork handler shall be called after
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
processing completes in the child process. If no handling is desired
Packit 7cfc04
at one or more of these three points, the corresponding fork handler
Packit 7cfc04
address(es) may be set to NULL.
Packit 7cfc04
.P
Packit 7cfc04
The order of calls to
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
is significant. The
Packit 7cfc04
.IR parent
Packit 7cfc04
and
Packit 7cfc04
.IR child
Packit 7cfc04
fork handlers shall be called in the order in which they were
Packit 7cfc04
established by calls to
Packit 7cfc04
\fIpthread_atfork\fR().
Packit 7cfc04
The
Packit 7cfc04
.IR prepare
Packit 7cfc04
fork handlers shall be called in the opposite order.
Packit 7cfc04
.SH "RETURN VALUE"
Packit 7cfc04
Upon successful completion,
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
shall return a value of zero; otherwise, an error number shall be
Packit 7cfc04
returned to indicate the error.
Packit 7cfc04
.SH ERRORS
Packit 7cfc04
The
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
function shall fail if:
Packit 7cfc04
.TP
Packit 7cfc04
.BR ENOMEM
Packit 7cfc04
Insufficient table space exists to record the fork handler addresses.
Packit 7cfc04
.P
Packit 7cfc04
The
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
function shall not return an error code of
Packit 7cfc04
.BR [EINTR] .
Packit 7cfc04
.LP
Packit 7cfc04
.IR "The following sections are informative."
Packit 7cfc04
.SH EXAMPLES
Packit 7cfc04
None.
Packit 7cfc04
.SH "APPLICATION USAGE"
Packit 7cfc04
None.
Packit 7cfc04
.SH RATIONALE
Packit 7cfc04
There are at least two serious problems with the semantics of
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
in a multi-threaded program. One problem has to do with state (for
Packit 7cfc04
example, memory) covered by mutexes. Consider the case where one
Packit 7cfc04
thread has a mutex locked and the state covered by that mutex is
Packit 7cfc04
inconsistent while another thread calls
Packit 7cfc04
\fIfork\fR().
Packit 7cfc04
In the child, the mutex is in the locked state (locked by a nonexistent
Packit 7cfc04
thread and thus can never be unlocked). Having the child simply
Packit 7cfc04
reinitialize the mutex is unsatisfactory since this approach does not
Packit 7cfc04
resolve the question about how to correct or otherwise deal with the
Packit 7cfc04
inconsistent state in the child.
Packit 7cfc04
.P
Packit 7cfc04
It is suggested that programs that use
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
call an
Packit 7cfc04
.IR exec
Packit 7cfc04
function very soon afterwards in the child process, thus resetting all
Packit 7cfc04
states. In the meantime, only a short list of async-signal-safe
Packit 7cfc04
library routines are promised to be available.
Packit 7cfc04
.P
Packit 7cfc04
Unfortunately, this solution does not address the needs of
Packit 7cfc04
multi-threaded libraries. Application programs may not be aware that a
Packit 7cfc04
multi-threaded library is in use, and they feel free to call any number
Packit 7cfc04
of library routines between the
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
and
Packit 7cfc04
.IR exec
Packit 7cfc04
calls, just as they always have. Indeed, they may be extant
Packit 7cfc04
single-threaded programs and cannot, therefore, be expected to obey new
Packit 7cfc04
restrictions imposed by the threads library.
Packit 7cfc04
.P
Packit 7cfc04
On the other hand, the multi-threaded library needs a way to protect
Packit 7cfc04
its internal state during
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
in case it is re-entered later in the child process. The problem
Packit 7cfc04
arises especially in multi-threaded I/O libraries, which are almost
Packit 7cfc04
sure to be invoked between the
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
and
Packit 7cfc04
.IR exec
Packit 7cfc04
calls to effect I/O redirection. The solution may require locking
Packit 7cfc04
mutex variables during
Packit 7cfc04
\fIfork\fR(),
Packit 7cfc04
or it may entail simply resetting the state in the child after the
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
processing completes.
Packit 7cfc04
.P
Packit 7cfc04
The
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
function was intended to provide multi-threaded libraries with a means
Packit 7cfc04
to protect themselves from innocent application programs that call
Packit 7cfc04
\fIfork\fR(),
Packit 7cfc04
and to provide multi-threaded application programs with a standard
Packit 7cfc04
mechanism for protecting themselves from
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
calls in a library routine or the application itself.
Packit 7cfc04
.P
Packit 7cfc04
The expected usage was that the prepare handler would acquire all mutex
Packit 7cfc04
locks and the other two fork handlers would release them.
Packit 7cfc04
.P
Packit 7cfc04
For example, an application could have supplied a prepare routine that
Packit 7cfc04
acquires the necessary mutexes the library maintains and supplied child
Packit 7cfc04
and parent routines that release those mutexes, thus ensuring that the
Packit 7cfc04
child would have got a consistent snapshot of the state of the library
Packit 7cfc04
(and that no mutexes would have been left stranded). This is good in
Packit 7cfc04
theory, but in reality not practical. Each and every mutex and lock
Packit 7cfc04
in the process must be located and locked. Every component of a program
Packit 7cfc04
including third-party components must participate and they must agree who
Packit 7cfc04
is responsible for which mutex or lock. This is especially problematic
Packit 7cfc04
for mutexes and locks in dynamically allocated memory. All mutexes and
Packit 7cfc04
locks internal to the implementation must be locked, too. This possibly
Packit 7cfc04
delays the thread calling
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
for a long time or even indefinitely since uses of these synchronization
Packit 7cfc04
objects may not be under control of the application. A final problem
Packit 7cfc04
to mention here is the problem of locking streams. At least the streams
Packit 7cfc04
under control of the system (like
Packit 7cfc04
.IR stdin ,
Packit 7cfc04
.IR stdout ,
Packit 7cfc04
.IR stderr )
Packit 7cfc04
must be protected by locking the stream with
Packit 7cfc04
\fIflockfile\fR().
Packit 7cfc04
But the application itself could have done that, possibly in the same
Packit 7cfc04
thread calling
Packit 7cfc04
\fIfork\fR().
Packit 7cfc04
In this case, the process will deadlock.
Packit 7cfc04
.P
Packit 7cfc04
Alternatively, some libraries might have been able to supply just a
Packit 7cfc04
.IR child
Packit 7cfc04
routine that reinitializes the mutexes in the library and all associated
Packit 7cfc04
states to some known value (for example, what it was when the image
Packit 7cfc04
was originally executed). This approach is not possible, though,
Packit 7cfc04
because implementations are allowed to fail
Packit 7cfc04
.IR *_init (\|)
Packit 7cfc04
and
Packit 7cfc04
.IR *_destroy (\|)
Packit 7cfc04
calls for mutexes and locks if the mutex or lock is still locked. In
Packit 7cfc04
this case, the
Packit 7cfc04
.IR child
Packit 7cfc04
routine is not able to reinitialize the mutexes and locks.
Packit 7cfc04
.P
Packit 7cfc04
When
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
is called, only the calling thread is duplicated in the child process.
Packit 7cfc04
Synchronization variables remain in the same state in the child as they
Packit 7cfc04
were in the parent at the time
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
was called. Thus, for example, mutex locks may be held by threads that
Packit 7cfc04
no longer exist in the child process, and any associated states may
Packit 7cfc04
be inconsistent. The intention was that the parent process could have
Packit 7cfc04
avoided this by explicit code that acquires and releases locks critical
Packit 7cfc04
to the child via
Packit 7cfc04
\fIpthread_atfork\fR().
Packit 7cfc04
In addition, any critical threads would have needed to be recreated and
Packit 7cfc04
reinitialized to the proper state in the child (also via
Packit 7cfc04
\fIpthread_atfork\fR()).
Packit 7cfc04
.P
Packit 7cfc04
A higher-level package may acquire locks on its own data structures
Packit 7cfc04
before invoking lower-level packages. Under this scenario, the order
Packit 7cfc04
specified for fork handler calls allows a simple rule of initialization
Packit 7cfc04
for avoiding package deadlock: a package initializes all packages on
Packit 7cfc04
which it depends before it calls the
Packit 7cfc04
\fIpthread_atfork\fR()
Packit 7cfc04
function for itself.
Packit 7cfc04
.P
Packit 7cfc04
As explained, there is no suitable solution for functionality which
Packit 7cfc04
requires non-atomic operations to be protected through mutexes and
Packit 7cfc04
locks. This is why the POSIX.1 standard since the 1996 release requires
Packit 7cfc04
that the child process after
Packit 7cfc04
\fIfork\fR()
Packit 7cfc04
in a multi-threaded process only calls async-signal-safe interfaces.
Packit 7cfc04
.SH "FUTURE DIRECTIONS"
Packit 7cfc04
None.
Packit 7cfc04
.SH "SEE ALSO"
Packit 7cfc04
.IR "\fIatexit\fR\^(\|)",
Packit 7cfc04
.IR "\fIexec\fR\^",
Packit 7cfc04
.IR "\fIfork\fR\^(\|)"
Packit 7cfc04
.P
Packit 7cfc04
The Base Definitions volume of POSIX.1\(hy2008,
Packit 7cfc04
.IR "\fB<pthread.h>\fP",
Packit 7cfc04
.IR "\fB<sys_types.h>\fP"
Packit 7cfc04
.SH COPYRIGHT
Packit 7cfc04
Portions of this text are reprinted and reproduced in electronic form
Packit 7cfc04
from IEEE Std 1003.1, 2013 Edition, Standard for Information Technology
Packit 7cfc04
-- Portable Operating System Interface (POSIX), The Open Group Base
Packit 7cfc04
Specifications Issue 7, Copyright (C) 2013 by the Institute of
Packit 7cfc04
Electrical and Electronics Engineers, Inc and The Open Group.
Packit 7cfc04
(This is POSIX.1-2008 with the 2013 Technical Corrigendum 1 applied.) In the
Packit 7cfc04
event of any discrepancy between this version and the original IEEE and
Packit 7cfc04
The Open Group Standard, the original IEEE and The Open Group Standard
Packit 7cfc04
is the referee document. The original Standard can be obtained online at
Packit 7cfc04
http://www.unix.org/online.html .
Packit 7cfc04
Packit 7cfc04
Any typographical or formatting errors that appear
Packit 7cfc04
in this page are most likely
Packit 7cfc04
to have been introduced during the conversion of the source files to
Packit 7cfc04
man page format. To report such errors, see
Packit 7cfc04
https://www.kernel.org/doc/man-pages/reporting_bugs.html .