kern/129172: [libc] signals are not delivered always
Jilles Tjoelker
jilles at stack.nl
Sat Oct 24 18:30:12 UTC 2009
The following reply was made to PR kern/129172; it has been noted by GNATS.
From: Jilles Tjoelker <jilles at stack.nl>
To: bug-followup at FreeBSD.org, Roman.Gritsulyak at gmail.com
Cc:
Subject: Re: kern/129172: [libc] signals are not delivered always
Date: Sat, 24 Oct 2009 20:26:29 +0200
It seems what you are looking for is not reliable delivery of signals,
but queuing of SIGCHLD in particular. This is implemented in FreeBSD 7.0
and newer. In FreeBSD 6 and older, SIGCHLD from child processes is not
queued: if another SIGCHLD signal arrives when one is already pending,
the two signals are coalesced and the handler is only called once.
Your test program should work fine if it calls waitpid(-1, NULL,
WNOHANG) from the signal handler until it returns 0 or -1.
Even when run on FreeBSD 7, the test program has some problems.
Firstly, it may exit before all the child processes.
Secondly, it assumes that wait() returns terminated child processes in
the same order as SIGCHLD signals. Apparently this is the case on Linux,
but it is not the case on FreeBSD. Then, when wait() returns status for
a different child process than the signal was for, the signal for that
child process is dequeued (POSIX prescribes this, and it must be that
way to limit the number of pending SIGCHLD signals to the number of
child processes). As a result, the zombie for the original child process
is never removed and the signal handler is called less than 100 times.
If you want to wait for one process per signal handler call, you can fix
this by making the handler a SA_SIGINFO one, and calling waitpid() with
si->si_pid where si is the siginfo_t pointer passed to the handler.
Otherwise use the simpler fix I mentioned above. Note that POSIX also
says that implementations may avoid queuing if SA_SIGINFO is not
enabled, but this is not the case in FreeBSD.
Thirdly, it uses unsafe functions with signal handlers. The use of
sem_wait() in a signal handler is not safe (apart from data consistency
issues with fast userspace implementations, the risk of deadlock is
pretty high -- a signal handler is not a thread). Only sem_post() is
async-signal-safe. It seems that the objective for the semaphore is
already met by the automatic blocking of a signal while its handler is
executing. printf() may also cause problems with signal handlers, and
also with fork() (double output).
--
Jilles Tjoelker
More information about the freebsd-bugs
mailing list