ChSigApplication

BApplication that understands POSIX signals

The ChSigApplication class is a BApplication that understands and can deal with POSIX signals.

Normally, a BApplication that receives a signal will be terminated, without mercy. By using ChSigApplication, you can handle the signals and exit gracefully.

Note: There are two signals, SIGKILL and SIGSTOP, that cannot be caught or ignored. SIGKILL will kill an application without mercy (or a chance to clean up after itself), and SIGSTOP will halt the application until a SIGCONT signal is received.

Hopefully, by providing handlers for "friendlier" signals, we can encourage users to use these friendly signals. Cross your fingers.


Constructor

#include "Ch/ChSigApplication.h"

ChSigApplication( const char *app_signature,
                  sigset_t *set = NULL,
                  int max_sig = NSIG );

Create a ChSigApplication with an application signature of app_signature; it will handle the signals defined in set.

The max_sig argument is for cases when an application might catch application-defined signals; this is for experts only. Read a good POSIX book's section on signals very carefully before you start messing with this sort of thing.

By defult, the ChSigApplication will catch and handle the following POSIX signals:

SIGHUP
Hangup; generated when the user closes the Terminal window (or exits the shell) that started your application.
SIGINT
Interrupt; generated when the user presses ^C in the shell that started your application.

set must be initialized using the POSIX signal set manipulation functions. For example, to catch SIGHUP and SIGINT, you'd do something like this:

    sigset_t set;

    (void)sigemptyset( &set );
    (void)sigaddset( &set, SIGHUP );
    (void)sigaddset( &set, SIGINT );

Methods

MessageReceived()

virtual void MessageReceived( BMessage *msg );

MessageReceived() is overridden to intercept the Ch_SIGNAL_RECEIVED message that's generated when the ChSigApplication catches a signal from the set specified in the constructor.

It also handles the Ch_QUIT_NOW message that's generated when the ChSigApplication should immediately quit in response to a signal.

IMPORTANT

If you override MessageReceived() in your own code, be sure to call ChSigApplication::MessageReceived( msg ) in the default: clause so Ch_SIGNAL_RECEIVED and Ch_QUIT_NOW can be handled properly.

SignalReceived()

virtual void SignalReceived( int signo );

SignalReceived() is called whenever the ChSigApplication receives a signal. signo will contain the signal number, which you can compare against the constants found in <signal.h>.

The default SignalReceived() method handles SIGHUP and SIGINT by calling the QuitDemanded() method; all other signals are ignored.

You do not need to call ChSigApplication::SignalReceived() if you override this method, unless you want SIGHUP and SIGINT to cause your program to quit gracefully.

QuitDemanded()

virtual void QuitDemanded( void );

This hook method is called whenever the application receives a "You must quit now!" signal, such as SIGHUP or SIGINT.

The default QuitDemanded() method immediately calls Quit().

If your application needs to save some state or otherwise clean up after itself, it can override QuitDemanded(). Note that this is not an optional quit request, like QuitRequested(); your application has been told to exit right now, and it will be considered a bug by your users if it doesn't.

IMPORTANT

If you override QuitDemanded() in your own code, be sure to call ChSigApplication::QuitDemanded() at the end of your QuitDemanded() processing.

IsValid()

virtual bool IsValid( void );

Is our ChSigApplication valid? Returns true if it is, or false if it isn't.

A ChSigApplication could be invalid if there are insufficient system resources to create a new thread or a new semaphore.


Important information about signals

This section is based on an excellent summary posted to the Be Developer's Mailing List by Howard Berkey and a subsequent response by Jon Wätte, as well as my own understanding of POSIX signals; thanks guys!

Signals and threads don't traditionally mix very well. The BeOS is actually quite good in this respect; the behaviour of signals with POSIX threads is (ahem) baroque, to say the least.

It's possible that if two signals came in while ChSigApplication is processing the signals that one would be lost, but who cares? If you're using signals heavily for interprocess communication these days you're just plain wrong. Especially on BeOS. ChSigApplication tries to do the right thing, but sending lots of signals to it very quickly could have strange results. This would also be the case on a "normal" UNIX system; signals aren't considered a reliable means of sending a message.

But, you should still be aware of signals; the user can easily send your hapless application a signal by using the kill command from the shell, or by using the kill function in an application.

Other tips:


Related stuff

The SigWorld application (available on BeWare, ftp.be.com, and Chris Herborth's BeOS Software page) also discusses making your application behave nicely in the face of POSIX signals, including source code examples.


Please see the libCh Overview for licensing information.


Last modified: $Date: 1998/04/11 19:41:01 $