OSF DCE Application Development Guide--Introduction and Style Guide

OSF DCE Application Development Guide—Introduction and Style Guide
2.3.4.4 Signal Rules
The following rules summarize correct signal handing practices for multithreaded
programs.
Signals must be blocked prior to being waited for. The sigwait( ) routine waits for
blocked (masked) signals.
In order to avoid unpredictable behavior, all asynchronous signal handling should be
confined to one signal catcher thread. This may be extended to a set of signal catcher
threads.
The pthread_cond_signal() routine cannot safely be used in a signal handler that is
invoked asynchronously. In general, mutexes and condition variables are not
suitable for releasing a waiting thread in response to a signal handler. When a thread
must wait for an asynchronous signal, use sigwait( ) instead.
Signal handlers should not call the pthread routines. In general, runtime libraries
cannot reliably be used in signal handlers.
2.3.5 Forking in a Threaded Application
The fork( ) system call causes the creation of an exact clone of the caller’s address space,
resulting in the execution by two address spaces of the same code. In order to avoid the
problems that would arise in a threaded environment when one thread, possibly without
the others’ knowledge, executes a fork(), the POSIX model defines fork( ) to result in
the propagation of the calling thread only. Any other active threads are immediately
terminated without notice.
The abrupt destruction of the other threads means that any mutexes they may have been
holding at the time of the fork( ) will persist in the locked (and therefore unacquirable)
state. On the other hand, assuming that the call to fork( ) is followed by a call to exec(),
then the outstanding mutexes will remain so only until exec( ) is called, when the new
process space will be reinitialized.
Thus, ‘‘out-of-state’’ mutexes are a problem for the forked thread only in the interval
between the fork() and the exec(). Even so, as long as no calls occur here to routines
outside the application, you can determine whether the thread is going to encounter any
mutexes that could have been locked by the destroyed threads. However, it is impossible
to be sure of this if calls into other libraries, which may have hidden interdependencies,
occur in this interval.
Aside from these considerations, there is also the question of what happens when exec()
fails and execution returns to the original forking (and now lone) thread, which is left
with an address space that may contain out-of-state mutexes (as well as an inconsistent
state in the data protected by the mutexes) as a result of the fork( ).
DCE does not support the ‘‘simple’’ fork( ); it supports only the fork() and exec()
sequence. For cases where forking in the presence of threads is felt to be necessary,
DCE threads provides a mechanism, the atfork( ) call, which allows you to install ‘‘fork
2 18 Tandem Computers Incorporated 124246