iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) (07/24/88)
Well, I guess I answered my own question out of necessity. Here is my attempt at writing an Exception Handler. The program will loop indefinitely, and catch the signals that result from typing either ^C, ^D, ^E, or ^F. In addition, ^C will abort the program. If people out there with experience in these matters see any mistakes I've made, please let me know.. Bill Kinnersley Physics Department BITNET: iphwk@mtsunix1 Montana State University INTERNET: iphwk%mtsunix1.bitnet@cunyvm.cuny.edu Bozeman, MT 59717 CSNET: iphwk%mtsunix1.bitnet@relay.cs.net (406)994-3614 UUCP: ...psuvax1!mtsunix1.bitnet!iphwk "He learned to communicate with birds and discovered that their conversation was fantastically boring. It was all to do with wind speed, wingspan, power-to-weight ratios and a fair bit about berries." ---------------- /* An illustration of how to write an Exception Handler */ /* Bill Kinnersley - IPHWK@MTSUNIX1.BITNET - 7/23/88 */ /* Compiled using Aztec 3.4a, 16-bit integers. */ /* ^D, ^E, ^F will print a message, ^C will abort. */ #include <stdio.h> #include <exec/types.h> #include <exec/tasks.h> #include <libraries/dos.h> #include <functions.h> extern short Enable_Abort; long aborted, cursigs, mysigs, oldsigs; struct Task *mytask; main() { /* Install my handler */ install(); /* Make sure that Aztec does not catch any ^C's */ Enable_Abort = 0; /* Busy loop simulating something useful... */ /* Note that each Exception DOES break into this loop. */ /* The aborted flag is polled only because */ /* I want to generate a clean exit from main(), */ /* not try to call cleanup from inside the handler. */ while (!aborted) {} /* It's essential to put things back the way they were */ /* Exceptions are task-specific, but all programs run */ /* from the same CLI will reuse the same Task structure */ cleanup(); } APTR oldcode; install() { int face(); mysigs = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F; mytask = FindTask(0L); /* Don't anyone else bother me while I'm changing my Task structure */ Forbid(); /* Save the old Exception Handler and install my own */ oldcode = mytask->tc_ExceptCode; mytask->tc_ExceptCode = (APTR)face; /* I won't use the tc_ExceptData field...leave it unchanged */ Permit(); /* Save the old Exception signals so we can put them back later */ oldsigs = SetExcept(mysigs, mysigs); } cleanup() { /* Restore the previous Exception Handler (ROM-wack?) */ Forbid(); mytask->tc_ExceptCode = oldcode; Permit(); SetExcept(0L,mysigs); } #asm _face: ;the signals will be passed to me in d0 move.l d0,-(a7) ;restore a4, which points to Aztec's small data segment */ public _geta4 jsr _geta4 move.l (a7)+,_cursigs jsr _hdlr ;return signals to the system so they can be reset move.l _cursigs,d0 rts #endasm hdlr() { /* Note that even AmigaDOS stuff can be done from here */ printf("Exception %lx Control-",cursigs); if (cursigs & SIGBREAKF_CTRL_C) {printf("C\n"); aborted=1;} if (cursigs & SIGBREAKF_CTRL_D) printf("D\n"); if (cursigs & SIGBREAKF_CTRL_E) printf("E\n"); if (cursigs & SIGBREAKF_CTRL_F) printf("F\n"); }
ewhac@well.UUCP (Leo L. Schwab) (07/27/88)
In article <3447@louie.udel.EDU> iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: >Well, I guess I answered my own question out of necessity. Here is >my attempt at writing an Exception Handler. [ ... ] > [ code deleted ] Congratulations, you got it. I would recommend that you also restore the tc_ExceptCode pointer when done as well; it may be important to someone. There are some caveats that you should be aware of. Kickstart does not internally interlock asynchronous operations. When you enter a Kickstart routine, the routine assumes that it will run to completion before returning to you. Thus, certain Kickstart routines may procure some resources upon entry, and free them upon exit. If you interrupt them and don't return, Bad Things will happen. As an example, suppose you call Draw(). Draw() calls OwnBlitter(), then performs weird sex on the blitter to draw the lines. If, during this time, your exception routine gets called, and your exception routines calls exit() or longjmp(), or in any way fails to return back to where it came from, you will have left the blitter allocated (since Draw() never got a chance to call DisownBlitter()). If you exit(), the system will appear to stop, since no one can get control of the blitter again. Similar situations exist in DOS. As long as your exception routine returns without trying to re-route the execution thread, you can use exceptions safely. However, be very careful of interrupting Kickstart routines; weird things may happen. You may wish to look at Matt Dillon's Qint routines which help alleviate this problem. _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Leo L. Schwab -- The Guy in The Cape INET: well!ewhac@ucbvax.Berkeley.EDU \_ -_ Recumbent Bikes: UUCP: pacbell > !{well,unicom}!ewhac O----^o The Only Way To Fly. hplabs / (pronounced "AE-wack") "Hmm, you're right. Air is made up of suspended meat loaf." -- Josh Siegel