Nick Stoughton wrote:
Interestingly, C++ have also been looking at this same issue, and are
intending to add the following requirement:
"The program shall ensure that all threads, except the main thread, have
terminated before calling exit or returning from main."
Interesting.
POSIX deliberately decided NOT to try to require this because of the
practical difficulties. For example, what if a thread is hung? You can't
call exit()? What HAPPENS if you call exit() while other threads are
running? Does it hang? Does exit() return a failure status and do
nothing? How do you manage dependencies between multiple modular
facilities that might use threads? Who's responsible for shutting them
down in the right order?
Or are we merely talking about a weasel-word disclaimer that "we're not
going to do anything to solve shutdown problems, so you either do it
yourself -- we won't tell you how nor give you any help -- or don't
complain to us when it doesn't work."
On Fri, 2008-06-06 at 14:31 +0100, Andrew Josey wrote:
[ This was blocked due to the attachment -- Andrew ]
Date: Fri, 06 Jun 2008 08:27:06 -0400
From: David Butenhof <david.butenhof@hp.com>
Organization: IS/MSL/iCAP
User-Agent: Thunderbird 2.0.0.14 (Windows/20080421)
MIME-Version: 1.0
To: Anoop <acv@linux.vnet.ibm.com>
CC: "austin-group-l@opengroup.org" <austin-group-l@opengroup.org>
Subject: Re: whether ext() and atexit() are safe w.r.t each other
References: <48491601.7030306@linux.vnet.ibm.com>
In-Reply-To: <48491601.7030306@linux.vnet.ibm.com>
Anoop wrote:
A race is observed between atexit() and exit() in Linux.
Does these functions need to be safe with respect to each other?
Being more specific, if a thread is registering a handler using atexit() while
exit() is processing the already registered handlers in the main thread,
what is the expected behavior as per the standard?
2.9.1 Thread-Safety
All functions defined by this volume of POSIX.1-200x shall be
thread-safe, except that the
following functions need not be thread-safe.
Neither atexit() nor exit() are on the list, therefore they must be
thread safe. Being thread safe means not subject to "unexpected
behavior" when called concurrently. This implicitly (but strongly and
unambiguously) requires synchronization between dependent functions.
(E.g., malloc and free, or exit and atexit.)
(I suppose one could make an argument that the standard should specify
and describe all such dependencies among the defined interfaces. That
might make it easier for "naive implementors", but it's hard to imagine
that any reasonable effort would identify all possible interactions; and
ultimately an implementor is still responsible for making the
implementation usable. I'll also agree that doesn't sound like a very
good excuse -- but someone would have to volunteer to get such an effort
started. While you're at it, you can work on a complete, consistent, and
comprehensible memory model. ;-) )
In any case, it clearly would not be acceptable for the application to
crash because exit() found the list of atexit() handlers in an
inconsistent state, for example. Nor for atexit() to crash because
exit() might modify the list.
There is, however, always a "race" between callers of dependent
functions. That is, it's not possible to define exit() so that it's
guaranteed to see all atexit() handlers that the application might ever
register (concurrently or in the future). But either exit() shall see
the new atexit handler and invoke it properly OR exit() shall not see
the new atexit handler and will proceed as if this call to atexit() had
not happened. Logically, exit() occurs either before or after atexit()
insertion; never "during".
The exit() function in particular has a lot of dependencies since it
cleans up and finalizes a lot of implicit user-mode process state "on
the way out". For example exit() can't crash because some thread is
opening a stdio stream, even though exit() must flush all streams.
Again, the new stream is either flushed because it's known to exit() as
open, or not flushed because it's not; but exit() must complete
successfully.
|