Next: Idle Callbacks and Timeouts, Previous: Doing Interaction, Up: Part V Overview of Main Functions [Contents][Index]
Typically, when a signal is delivered, the application does not know what state the application is in, thus limiting the tasks a signal handler can do. In a GUI system and with a main loop inside the library, it’s even harder to know what’s safe or unsafe to do in a signal handler. Given all these difficulties, the Forms Library’s main loop is made to be aware of signal activities and invoke signal handlers only when it’s appropriate to do so, thus removing most limitations on what a signal handler can do.
The application program can elect to handle the receipt of a signal by registering a callback function that gets called when a signal is caught
typedef void (*FL_SIGNAL_HANDLER)(int, void *); void fl_add_signal_callback(int signal, FL_SIGNAL_HANDLER sh, void *data);
Only one callback per signal is permitted. By default,
fl_add_signal_callback()
will store the callback function
and initiate a mechanism for the OS to deliver the signal when it
occurs. When the signal is received by the library, the main loop will
invoke the registered callback function when it is appropriate to do
so. The callback function can make use of all of XForms’s functions as
well as Xlib functions as if they were reentrant. Further, a signal
callback registered his way is persistent and will cease to function
only when explicitly removed.
It is very simple to use this routine. For example, to prevent a program from exiting prematurely due to signals, a code fragment similar to the following can be used:
void clean_up(int signum, void *data) { /* clean up, of course */ } /* call this somewhere after fl_initialize() */ fl_add_signal_callback(SIGINT, clean_up, &mydata);
After this, whenever a SIGINT
signal is received,
clean_up()
is called.
To remove a signal callback, the following routine should be used
void fl_remove_signal_callback(int signal);
Although very easy to use, there are limitations with the default
behavior outlined above. For example on some platforms there is no
blocking of signals of any kind while handling a signal. In addition,
use of fl_add_signal_callback()
prevents the application
program from using any, potentially more flexible, system signal
handling routines on some platforms. Also there might be perceptible
delays from the time a signal is delivered by the OS and the time its
callback is invoked by XForms’ main loop. This delay can be particular
troublesome for timing sensitive tasks (playing music for example).
In light of these limitations, provisions are made so an application
program may choose to take over the initial signal handling setup and
receipt via various system dependent methods (sigaction()
for
example).
To change the default behavior of the built-in signal facilities, the
following routine should be called prior to any use of
fl_add_signal_callback(
) with a true value for flag
:
void fl_app_signal_direct(int flag);
After this call fl_add_signal_callback()
will not
initiate any actions to receive a signal. The application program
should handle the receipt and blocking of signals (via e.g.,
signal(2)
, sigaction(2)
, sigprocmask(2
) etc.) When
the signal is received by the application program, it should call the
following routine to inform the main loop of the delivery of the
signal signum
, possibly after performing some timing sensitive
tasks:
void fl_signal_caught(int signum);
This routine is the only one in the library that can be safely called
from within a direct application signal handler. If multiple
invocations of fl_signal_caught()
occur before the main
loop is able to call the registered callback, the callback is called
only once.
The following example illustrates how to handle a timing critical
situation (for most application, idle callback, timeouts or
FL_TIMER
object should be sufficient).
First, you need to define the function that will handle the timing critical tasks. The function will be registered with the OS to be invoked directly by it. There are limitations on what you can do within a (OS) signal handler, in particular, GUI activity is not safe.
void timing_critical_task(int sig) { /* handle timing critical tasks that does not involve GUI */ ... /* Now tell the library the signal has been delivered by the OS. * The library will invoke the xforms signal handler when it's * appropriate to do so */ fl_signal_caught(sig); }
Now define a (XForms) signal handler that will be responsible for handling the response of the GUI upon receipt of the signal
void gui_signal_handler(int sig, void *data) { /* within an XForms signal handler, there is no limitation * on GUI activitity */ fl_set_object_color(....); ... }
To make all this work, a set-up similar to the following can be used
/* setup the signal */ fl_app_signal_direct(1); setitimer(ITIMER_REAL, interval); /* setup the OS signal handler */ signal(SIGALRM, timing_critical_tasks); /* setup the XForms signal handler */ fl_add_signal_callback(SIGALRM, gui_signal_handler, &myData);
Next: Idle Callbacks and Timeouts, Previous: Doing Interaction, Up: Part V Overview of Main Functions [Contents][Index]