Best Way to Print Nature of Signal

Discussion in 'C Programming' started by Martin McCormick, Oct 22, 2003.

  1. A C program contains several signal statements to remove a
    lock file if the program gets killed:

    /*Set up interrupt handler to catch ctrl-C so that lock file can be removed.*/
    signal(SIGINT,crash);
    signal(SIGBUS,crash);
    signal(SIGSEGV,crash);

    This part works. Those signals cause the "crash.c" module to
    run and get rid of the lock. Is there a standard way to also print
    the error the user of the program would have seen so that whoever
    runs the program knows that something bad happened? With the
    signal handler, the program silently finishes which might make
    someone think it was successful when in reality, it just did nothing
    and abended. Thank you.
    --

    Martin McCormick WB5AGZ Stillwater, OK
    Information Technology Division Network Operations Group
     
    Martin McCormick, Oct 22, 2003
    #1
    1. Advertising

  2. In article <bn6n9a$mek$>,
    Martin McCormick <> wrote:
    >
    > A C program contains several signal statements to remove a
    >lock file if the program gets killed:
    >
    >/*Set up interrupt handler to catch ctrl-C so that lock file can be removed.*/
    >signal(SIGINT,crash);
    >signal(SIGBUS,crash);
    >signal(SIGSEGV,crash);
    >
    > This part works. Those signals cause the "crash.c" module to
    >run and get rid of the lock. Is there a standard way to also print
    >the error the user of the program would have seen so that whoever
    >runs the program knows that something bad happened? With the
    >signal handler, the program silently finishes which might make
    >someone think it was successful when in reality, it just did nothing
    >and abended. Thank you.


    Be aware (I have to say this or people will jump on me and start
    stuffing socks down my throat) that it's impossible (or at least
    Extremely Difficult) to do this without invoking undefined behavior,
    because the set of functions you're allowed to call from a signal handler
    is extremely limited[1]. There's a good chance, however, that your
    implementation defines the behavior of doing something like this to be
    "what you would expect", and you're almost certainly already relying on
    this to be able to clean up the lock before the program terminates.

    For more details on what your implementation (as opposed to the language)
    allows you to do in a signal handler, a newsgroup for your platform may
    be more useful.

    The signal handler gets the signal as its parameter, so a crash() that
    looks something like this will probably come close to doing what you want:
    --------
    void crash(int sig)
    {
    do_cleanup();
    #if USE_ALTERNATIVE_1
    /*Alternative 1: Now that we've done the cleanup, let the default
    signal handler dump core or whatever
    */
    if(signal(sig,SIG_DFL)==SIG_ERR);
    {
    fputs("This is odd, can't revert to default signal handler\n",stderr);
    abort();
    }
    raise(sig);
    /*We shouldn't get here, but to be sure:*/
    return;
    #else
    /*Alternative 2: After doing cleanup, inform user that we terminated
    abnormally, but bypass the default signal handler
    */
    fprintf(stderr,"Terminating abnormally (signal %d received)\n",sig);
    exit();
    #endif
    }
    --------
    The boring standardese details:
    Alternative #2 isn't allowed for asynchronous signals (which the ones
    you're handling probably are), because you're not allowed to call most
    standard library functions[1]. You're probably not doing anything worse
    than you're already doing in do_cleanup(), though.
    Alternative #1 is slightly more problematic, since you're not allowed
    to call raise() in a signal handler invoked by calling raise() either.
    In practice, though, it (like alternative #2) isn't likely to be any
    worse than do_cleanup() is already doing.


    dave

    [1] To be precise, signal() with a first argument equal to the signal
    that resulted in the handler being called or abort() when handling
    an asynchronous signal, (rather more generously) anything but raise()
    when handling a signal raised by raise().

    --
    Dave Vandervies
    If he'd got it wrong (and it happens to us all), several people would
    have jumped on him and started stuffing socks down his throat.
    --Richard Heathfield in comp.lang.c
     
    Dave Vandervies, Oct 22, 2003
    #2
    1. Advertising

  3. Martin McCormick

    Micah Cowan Guest

    (Martin McCormick) writes:

    > A C program contains several signal statements to remove a
    > lock file if the program gets killed:
    >
    > /*Set up interrupt handler to catch ctrl-C so that lock file can be removed.*/
    > signal(SIGINT,crash);
    > signal(SIGBUS,crash);
    > signal(SIGSEGV,crash);
    >
    > This part works. Those signals cause the "crash.c" module to
    > run and get rid of the lock. Is there a standard way to also print
    > the error the user of the program would have seen so that whoever
    > runs the program knows that something bad happened? With the
    > signal handler, the program silently finishes which might make
    > someone think it was successful when in reality, it just did nothing
    > and abended. Thank you.


    Unfortuately, there is no way to do what you want in standard
    C. Any of the standard facilities for writing text to a file
    (including the terminal) may not be called from a signal handler
    that was called due to an exception. If the handlers were
    expected to return normally, then I would have recommended
    writing to an object declared with "volatile sig_atomic_t" type
    and check for it elsewhere; but as they probably don't
    (/shouldn't) return, you can't do that.

    <OT>
    However, as you seem to be using non-standard signals to begin
    with (SIGBUS), and apparently expect ctrl-C to generate SIGINT,
    I'll hazard an educated guess that you're on a UNIX-style system
    with access to POSIX extensions. So I'd recommend that you post
    this question on comp.unix.programmer, where they will very
    likely be able to help you take advantage of non-"Standard C"
    POSIX extensions that may aid you. I've taken the liberty of
    cross-posting this there: but please follow-up to there *only*, if
    you will not be discussing ISO C.

    POSIX allows you to call such functions as write(), which would
    allow you to write a message to the terminal; but there may still
    be unflushed data that is in the stdout/stderr buffer, but still
    not yet actually written out: you'll need to take care of that.

    You might also consider adding whether or not this handler would
    be appropriate for other signals such as SIGABRT, SIGHUP, SIGTERM...
    </OT>

    HTH, HAND.
    --
    Micah J. Cowan
     
    Micah Cowan, Oct 22, 2003
    #3
  4. Hi Martin!

    > > A C program contains several signal statements to remove a
    > > lock file if the program gets killed:
    > >
    > > /*Set up interrupt handler to catch ctrl-C so that lock file can be
    > > removed.*/
    > > signal(SIGINT,crash);
    > > signal(SIGBUS,crash);
    > > signal(SIGSEGV,crash);
    > >
    > > This part works. Those signals cause the "crash.c" module to
    > > run and get rid of the lock. Is there a standard way to also print
    > > the error the user of the program would have seen so that whoever
    > > runs the program knows that something bad happened? With the
    > > signal handler, the program silently finishes which might make
    > > someone think it was successful when in reality, it just did nothing
    > > and abended. Thank you.


    If you have a POSIX conform implementation, you can use write() (but not
    the printf() family!) in your signal handler. The function write() is
    async-signal-safe, which means that you can use it without any problem
    in signal handler. The standard file descriptor for stdout resp. stderr are
    STDOUT_FILENO, resp STDERR_FILENO.

    BTW, use sigaction() instead of signal() (though I believe that modern
    Un*x implement signal() using sigaction()). This will make your program
    more "reliable" wrt. signals catching.

    HTH,
    Loic.
    --
    Article posté via l'accès Usenet http://www.mes-news.com
    Accès par Nnrp ou Web
     
    Loic Domaigne, Oct 23, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lau Lei Cheong

    The nature of string and char[] in .NET

    Lau Lei Cheong, Jun 4, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    445
    Natty Gur
    Jun 5, 2004
  2. Johnny
    Replies:
    1
    Views:
    397
    Steve R.
    Mar 5, 2004
  3. keto
    Replies:
    0
    Views:
    1,056
  4. David Cournapeau

    print a vs print '%s' % a vs print '%f' a

    David Cournapeau, Dec 30, 2008, in forum: Python
    Replies:
    0
    Views:
    409
    David Cournapeau
    Dec 30, 2008
  5. Sam
    Replies:
    10
    Views:
    71
    flebber
    Feb 15, 2014
Loading...

Share This Page