home *** CD-ROM | disk | FTP | other *** search
- Submitted-by: gwyn@smoke.brl.mil (Doug Gwyn)
-
- In article <1s8s8bINNl4h@ftp.UU.NET> wulkan@vnet.IBM.COM (Mike Wulkan) writes:
- >1) ANSI C Standard Section 4.10.4.1 abort():
- > "...causes abnormal program termination to occur, unless the signal
- > SIGABRT is being caught and the signal handler does not return. ...
- > is returned to the host environment by means of the function call
- > raise(SIGABRT)."
- >2) Posix .4a Section 2.2.1.136:
- > "Asynchronously generated signal: A signal which is not
- > attributable to a specific thread. Examples are signals sent via
- > kill(), ..."
- >3) Posix .4a Section 8.4.6.2:
- > "The C standard raise() function... The effect of this function in
- > a POSIX.4a process shall be equivalent to calling
- > kill(getpid(),sig). The signal specified shall be asynchronously
- > generated, regardless of the signal number, providing the signal
- > number is valid."
- >I think that it is pretty clear from the above that abort() causes an
- >asynchronous SIGABRT signal to be generated.
-
- Yes, to the extent that "asynchronous" is (re)defined as per POSIX.4a,
- where it seems to mean "process global".
-
- >So how do you achieve the semantics required by (1) if the SIGABRT signal
- >is delivered to a thread other than the one that issued the abort() call?
-
- Well, the first thing to note is that the C standard specifies only what
- is guaranteed for STRICTLY CONFORMING programs, which excludes any program
- that uses POSIX.4a thread facilities. So, strictly speaking, there is
- no standard requirement imposed by (1) in such circumstances.
-
- >What you end up with is a race condition between the thread that is
- >executing the SIGABRT signal handler and the thread that issued the
- >abort() function call terminating the program!
-
- Any time you have multiple threads you already have a race.
-
- >AND the method of exiting the signal handling function has NO influence
- >on whether the program will be terminated. This is a direct violation
- >of ANSI C.
-
- I didn't understand that comment at all. Certainly the POSIX.4a
- requirement for the implementation of raise() is compatible with the
- requirements of the C standard. And I saw nothing in the cited specs
- that requires that abort() be implemented any differently for POSIX.4a
- than for POSIX.1. I have attached my implementation below for your
- perusal.
-
- >Even in the case where the SIGABRT signal is delivered to the same
- >thread that issued the abort() function call, since the signal is
- >asynchronous, there is NO guarantee that it will be delivered before the
- >abort() function initiates termination of the program.
-
- I think that is simply a misconception of the way that abort() must
- operate. It is the unintercepted SIGABRT, generated by abort(), that
- CAUSES (abnormal) program termination.
-
- In the comments below, "asynchronous" means "asynchronous", not the
- POSIX.4a redefinition of the term.
-
- /*
- abort() -- generate an abnormal process termination
-
- public-domain implementation
-
- last edit: 13-Dec-1992 Gwyn@ARL.Army.Mil
-
- complies with the following standards:
- ANSI/ISO 9899:1990[1992] (replaces ANS X3.159-1989)
- ISO/IEC 9945-1 (Replaces IEEE Std 1003.1-1988)
- SVID Issue 3
- XPG Issue 3
- AES Revision A
-
- IMPLEMENTOR NOTE: abort() must be reentrant for other signals
- that may occur asynchronously, resulting in additional
- calls to abort() from their handler functions.
- Consequently, the STDIO cleanup function must also be
- reentrant or else it must block signals and be serially
- reusable.
- */
- #ifdef __ORCAC__
- #pragma lint -1
- #pragma optimize -1
- #pragma noroot
- #endif
-
- /* IMPORTANT: Define CLEANUP to invoke your STDIO cleanup function: */
- #ifdef unix
- extern void _cleanup();
- #define CLEANUP _cleanup(); /* usual invocation through SVR2 */
- #else
- #ifdef __ORCAC__
- #define SysIOShutdown SYSIOSHUTDOWN /* temporary, for ORCA/C 2.0.0 D6 */
- extern pascal void SysIOShutdown( void );
- #define CLEANUP SysIOShutdown(); /* ~C_SHUTDOWN undoubtedly better */
- #else
- #define CLEANUP /* XXX -- define yours here -- XXX */
- #endif
- #endif
-
- #define _POSIX_SOURCE /* force visibility of POSIX.1 symbols, if any */
- #include <signal.h>
-
- typedef void (*sigf_type)(
- #ifdef __STDC__
- int
- #endif
- );
-
- #ifndef SIGABRT
- #define SIGABRT SIGIOT /* UNIX tradition */
- #endif
-
- void
- abort(
- #ifdef __STDC__
- void
- #endif
- )
- {
- register sigf_type sigfunc = signal( SIGABRT, SIG_IGN );
- #ifdef SIG_BLOCK /* POSIX.1 support assumed */
- sigset_t abort_mask;
-
- (void)sigemptyset( &abort_mask );
- (void)sigaddset( &abort_mask, SIGABRT );
- (void)sigprocmask( SIG_UNBLOCK, &abort_mask, (sigset_t *)0 );
- /* If a SIGABRT signal was pending, it has now been discarded. */
- #endif
-
- if ( sigfunc == SIG_IGN )
- sigfunc == SIG_DFL;
-
- if ( sigfunc == SIG_DFL )
- CLEANUP /* flush STDIO buffers etc. */
-
- for ( ; ; )
- {
- (void)signal( SIGABRT, sigfunc );
- /* SIG_DFL or function */
- (void)raise( SIGABRT ); /* wham? */
-
- /* The program caught SIGABRT and the handler returned. */
-
- sigfunc = SIG_DFL; /* force bam! */
- }
- }
-
-
- Volume-Number: Volume 31, Number 54
-
-