[cfe-dev] Why clang needs to fork into itself?
Tom Honermann
thonermann at coverity.com
Wed Jan 29 08:18:40 PST 2014
On 01/29/2014 06:18 AM, Yuri wrote:
> On 01/29/2014 02:57, Yury Gribov wrote:
>> I'm not sure e.g. exec calls realloc and I'm not sure what kinds of
>> crazy stuff CreateProcess may want to do behind your back.
>
> Create process calls (clone or fork) never call realloc, they are atomic
> system calls. They don't do any crazy stuff. Same should be true on
> windows. But, in the suggested way no additional process creation is
> required.
This is not quite true. fork() is not async-signal-safe in a
multithreaded process. Quoting from POSIX 2008
(http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)
<quote>
When the application calls fork() from a signal handler and any of the
fork handlers registered by pthread_atfork() calls a function that is
not async-signal-safe, the behavior is undefined.
</quote>
In particular, glibc establishes pthread_atfork() handlers that can
cause calls to fork() to hang in a signal handler (in a multi-threaded
process). I've experienced this many times when a thread was
interrupted while in a call to malloc() (usually due to some memory
mismanagement issue). The hang occurs because one of the glibc
pthread_atfork() registered handlers attempts to acquire a lock
previously acquired by malloc().
The Austin Group has a defect report tracking the addition of an _Fork()
interface that would be async-signal-safe in all processes. See
http://austingroupbugs.net/view.php?id=18. I'm not sure what the
current state of that proposal is.
The above applies only to multi-threaded processes and only to the use
of fork() in a signal handler, so does not necessarily apply here since,
as far as I know, the Clang driver is not currently multi-threaded.
However, the driver would have to be specifically built and linked
without support for threads (whether they are created or not) to avoid
problems with the use of fork() in a signal handler (or would need to
use an equivalent to _Fork()).
Despite the above, I agree that writing a signal handler to produce
defect reports from a crashing process is *possible*. I've done it
before (and had to write my own implementation of _Fork() - available as
sigfork() at
http://permalink.gmane.org/gmane.comp.standards.posix.austin.general/160).
However, it is *extremely* difficult to make reliable across all
platforms and will very likely require platform specific coding.
Reliable signal programming is *hard*. And in this case, the
requirements are even more strict than async-signal-safety because
synchronous signals raised due to a processor exception (such as
SIGSEGV) cannot be blocked which means that
pthread_sigmask()/sigprocmask() protected critical sections may be
interrupted. This means you can't even reliably call async-signal-safe
functions from the signal handler.
Tom.
More information about the cfe-dev
mailing list