07-19-06 01:04 PM
I'm seeing a race condition when fork/exec'ing a process. My process
catches SIGTERM to do some cleanup, but also sends SIGTERM to processes
that it fork/exec's (to quit them as needed). The problem is that my
process (the parent) calls fork and then continues its normal
processing. The child of the fork does an exec, but if its parent (my
process) sends that child a SIGTERM in the window between fork and
exec, the child is still running the code of my process so it ends up
running the SIGTERM handler of the child instance of my process. My
SIGTERM handler writes to an internal IPC pipe to tell a thread to
quit. Because file descriptors are inherited, this ends up causing the
thread in the parent process to think it needs to quit when the child
get a SIGTERM in this window (some signal handlers are in libraries so
I can't just check the pid).
I thought I could just block all signals before fork and restore them
in the parent after fork, but it seems sigprocmask is preserved even
across exec so any signals ignored in the parent would end up also
being ignored in the newly exec'd process, which I don't want because
that process may want the default behavior for those signals.
The best I could come up with is to block all signals before fork then
from the child, reset signals I know the parent has ignored and unblock
all signals in the child before calling exec, like this:
sigfillset( &newSet );
sigprocmask( SIG_BLOCK, &newSet, &oldSet );
pid = fork();
if( pid == 0 ) // Child
{
signal( SIGPIPE, SIG_DFL ); // SIGPIPE was ignored in parent
sigfillset( &newSet );
sigprocmask( SIG_UNBLOCK, &newSet, NULL );
exec...
}
else
{
sigprocmask( SIG_SETMASK, &oldSet, NULL );
}
Is this good enough? Is there an easier way? I don't like that I have
to just "know" which signals I've ignored and reset them explicitly
because my process uses lots of libraries that may ignore signals
behind my back. I didn't see any sigset iteration functions. I was
hoping for some way to say "exec this process, but restore all signals
to their defaults".
[ Post a follow-up to this message ]
|