[comp.windows.x] Handling signals in X

dheller@cory.Berkeley.EDU (Dan Heller) (05/16/89)

In article <8905152110.AA20907@expo.lcs.mit.edu> kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) writes:

> >   There could
> > be a SIGIO event delivered to the application's event handler for that signal
> > interrupting something critical within Xt.  If this routine does more Xt 
> > calls, then all sorts of havoc can result.

> You need to remember that not everyone has UN*X, the toolkit attempts to allow
> common I/O functions for all operationg systems.  Now we can take
> advantage of the fact the UN*X treates sockets the same as any other
> file descriptor and use XtAddInputHandler to add a callback routine
[etc... etc...]

What you said is all nice and interesting, but it doesn't address the issue
I brought up.  I used the socket/SIGIO example because it was the "current
topic."  The major problem that I was pointing out is that there is no provision
whatsoever in X or the intrinsics to handle *signals*, however they are
generated.  SIGIO is but one of many.

One signal that the intrisics code does handle is SIGALRM in the form of
XtAddTimeOut().  No, it doesn't deal with the signal directly and unless you
use the intrinsics, it is virtually impossible to handle frequent SIGALRMs in
Xlib.  The intrinsics code expects the user to use the provided interface for
the signal and reap the same results as he would if he were to set up a
signal handler for alarms himself.  But why stop there?

Both X and the intrinsics need to handle -all- signals intelligently, or
disaster is definitely awaiting.  Consider the delivery of a SIGPIPE because
a read from a socket failed.  Or the delivery of a SIGTERM because someone
wants to terminate the client.  The application definitely needs to handle
this signal appropriately.  But doing so could interrupt a critical Xlib or
Xt function.  The server could be very busy and asynchronous with the client.

The client is sending lots of data over the wire when suddenly, a signal
interrupts a routine deep in Xlib and the protocol may be interrupted.
The application's signal handler wants to display a dialog box:
    Recived Signal! Continue? Y/N
Obviously, this example is simple, but the point remains.

If there is interest in the X consortium, I'd like to initiate conversation
to generate a formal proposal for dealing with this issue.  There are many
things to consider, but generally what needs to happen is to design some
sort of interface for handling signals.

Here is an example of the type of thing that I consider would be a minimum
requirement of the toolkit intrinsics:

typedef XtSignal (*void)();	/* very unix/system dependent */
typedef enum {
    PRIORITY_SAFE;
    PRIORITY_IMMEDIATE;
    ... /* more? */
} XtPriorityLevel;

    XtSignalFunc
    XtSignalHandler(signal, handler, priority)
	int signal;
	XtSignalFunc handler;
	XtPriorityLevel priority;

If the priority is "safe", then the intrinsics deliver the signal when it
is safe to do so.  If it's "immediate", then the signal is delivered to the
application as soon as it occurs.  Obviously, there is much responsibility
on the programmer to know which priority to choose.  The routine will return
the old handler (pointer to a function returning the appropriate type [void,
int]) so that the programmer can reinstall the previous function (and to
more closely mimic signal()).

Let's say that the application wants to handle SIGTERM in the function foo().

XtSignal oldhandler = XtSignalHandler(SIGTERM, foo);

Now, the intrinsics would know about this and catch the signal itself
if it gets delivered.  If the intrinsics are in a state in which it
would be "bad" to be interrupted -- if the toolkit just has to finish
a particular operation -- internal magic then happens which flags the
signal as being delivered and it would continue with its operations
until it is safe and then deliver the signal to the user by calling
foo().

The "foo" function is undefined here -- it could be designed to be just
like the default way signal handlers are called including all args, or
it could add more info, such as the "actual time" the event got delivered,
the type of priority that got set, etc...

This seems to be the type of thing that should be installed in Xlib as
well as Xt.  I can see it in both because both libraries have sensitive
areas which, if interrupted jeapordize the state of the "machine" and
unpredictable results may occur.  I can also see it in just Xt because
of the same reason that XtAddTimeOut exists.

Dan Heller	<island!argv@sun.com>

nmm@cl.cam.ac.uk (Nick Maclaren) (05/17/89)

dheller@cory.Berkeley.EDU (Dan Heller) writes:

> Both X and the intrinsics need to handle -all- signals intelligently, or
> disaster is definitely awaiting. ....

I agree, but Chris D. Peterson is also right about the fact that not everyone
has UNIX.  I am afraid that designing this area is EXTREMELY nasty and there
are very few people in the world with the requisite skills.  Yes, it needs
to be done, but it must be done extremely carefully and with great attention
paid to getting as wide a range of input as possible.

For example, there are 4 'ANSI' C compilers for IBM MVS, which is about as
different from UNIX as you can hope to achieve.  Only one of these (the one
I wrote!) supports longjmp from out of a SIGINT handler called from within
I/O (e.g. waiting for terminal input).  Whether this can be done is clearly
critical to the design of the X signal handling.

The ANSI C description of signal handling is about as portable as anything
I have seen that is flexible enough to use.  However, there are a good many
aspects of its design that are severely system-dependent, and cannot be done
on systems that use an exception model that is radically different from the
UNIX one.  I could go into details, but I don't think this forum is
appropriate.

The X Consortium are quite right to have stayed out of this minefield so far,
even though it needs to be crossed at some stage.

Nick Maclaren
University of Cambridge Computer Laboratory
nmm @ cl.cam.ac.uk

nmm@cl.cam.ac.uk (Nick Maclaren) (05/17/89)

I apologise for a misediting in my previous entry.  I did NOT write the
compiler that I am referring to!  I wrote only the MVS-dependent part of
the run-time system, and had no part in the writing of the compiler.

Nick Maclaren