Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!samsung!brutus.cs.uiuc.edu!wuarchive!texbell!texsun!newstop!sun!turnpike!argv From: argv%turnpike@Sun.COM (Dan Heller) Newsgroups: comp.windows.x Subject: Re: Problem with Signals Message-ID: <132606@sun.Eng.Sun.COM> Date: 7 Mar 90 01:55:56 GMT References: <9002281729.AA02895@wilkins.bcm.tmc.edu> <132399@sun.Eng.Sun.COM> <23695@masscomp.ccur.com> Sender: news@sun.Eng.Sun.COM Reply-To: argv@sun.UUCP (Dan Heller) Lines: 139 BTW, the recent discussion of XtCleanup() or XtExit() makes this discussion even more important. Trapping signals reliably will aid in the programmer being able to call XtExit() as needed. In article <23695@masscomp.ccur.com> mitch@westford.ccur.com (Mitchel Kuninsky) writes: > argv wrote the following: > >Now, you could implement this yourself via "work procs" > >(see XtAddWorkProc()), but the granularity isn't fine enough. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Note #1) > >That is, work procs are only called when there are no events > >pending. Implemented properly, the internals to Xt would > >check in between event delivery to event handlers. ^^^^^^^^^^^^^^^^^^^^^^^^^ (note #2) > Are you suggesting that you do an XtAddWorkProc from the signal > handler? Not exactly. There are two ways to address this: one where Xt is modified and the other for when Xt is not modified (e.g. you have write the necessary functions). I claim that the best solution is a modification to Xt. However, I suggested a "workaround" for the timebeing. This is the use of "work procs". From the top: the first call to AddSignalHandler(sig, proc) does: AddSignalHandler(sig, handler) int sig; SIGRET (*handler)(); { SIGRET old_hanlder = signal(sig, _private_func); /* see below */ /* add to a linked list (data struct, whatever) the fact that "handler" should be called when "sig" is delivered. */ return old_handler; } The _private_func is static to the .c file that is implementing this stuff. It would have code which does: static long signal_received = 0L; /* bitmask indicating delivered sigs */ static _private_func(sig, ...) int sig; ... { /* save signal context, resources, etc... in a *queue* because the same signal may have been delivered more than once before processing. */ if (!signal_received) /* no signals registered so far, add work proc */ XtAddWorkProc(_check_sigs, NULL); /* see below */ signal_received |= (1< Just about > the ONLY thing you can do safely from a signal handler is set a flag. which is exactly what I'm doing. > One solution to this problem, as you mention in your message, is to set > a flag and use a modified XtMainLoop that checks the flag upon return > from XtNextEvent before calling XtDispatchEvent. I've implemented ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > something like this and the one problem I have is that the arrival of > the signal will not kick the client out of XtNextEvent so your signal > handler will not get executed until some other event comes along. That's not the way to do it. You *must* do this from _within_ XtNextEvent(). You should not wait till afterwards. As my "notes" (#1 and #2 in the beginning of my message) point out, one way of getting out of XtNextEvent() quickly is by a work proc, but the graunliary isn't fine enough -- you have to wait for all queued events to be delivered before getting notified of the signal. Thus, to really modify XtNextEvent correctly, you have to add a test for the "signal_received" bitmask (!= 0) at the this location within the Xt code: void XtAppNextEvent(app, event) XtAppContext app; XEvent *event; { int i, d; for (;;) { add -> if (app->signal_received != 0) add -> /* call the equivalent to the work proc above */ if (app->count == 0) DoOtherSources(app); else { for (i = 1; i <= app->count; i++) { . . . Note: "signal_received" does not necessarily have to be atteched to an application context, but let's not get into that right now. > Usually, this is no problem, but, if the signal you're catching is > SIGQUIT, there probably will not be any more events coming from the > user. Oh yeah? If you've trapped it, you will certainly get a bunch of events from the user. Because he sees that the application is not quitting, he's going to do it again, click on the "quit" button and ask "why is this application not quitting?" while he moves his mouse around, pushes keys and presses buttons. > The real root of this problem, at least on Unix systems, is that the > select in the Xlib tries to recover from being interrupted by a signal > by checking errno for EINTR (which is the value returned when a system > call is interrupted by a signal). If it finds EINTR, it just dives This is only a problem on sys-v for one. But, Xt already does this so it's not terribly important to continue to address this problem. dan ----------------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com 632 Petaluma Ave, Sebastopol, CA 95472 800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104 Opinions expressed reflect those of the author only.