Gribnif@UMass.BITNET (Dan Wilga at UMASS Amherst) (02/02/88)
Greetings, I realize there have probably been atleast two buzillion (okay, I'm exaggerating, one buzillion) questions relating to TOS' handling of the <Control> C key and ways of disabling it, but I'm sure we could all use a refresher course by now... :-) I have found that using the XBIOS (or are they BIOS??) functions Cconws/Cconout to send information to the console is actually quite nice for the application I am writing, since they allow the user to use <Control> Q and <Control> S for flow control of the data on the screen (whereas the "raw" output functions beginning with "B" do not.) The problem is that as soon as the user enters a <Control> C the program is immediately terminated with a status -32. Not nice. So it all boils down to this: has anyone found a LEGAL way (short of redefining the keyboard, assuming TOS is looking for the ASCII and not the scan code--redefining it would be inefficient for me anyway) of disabling or trapping the key so that the program is not terminated? Moshe? Second of all I would like to know how programs like GEMSTART work and if they can, in fact, work with the new ROMs without modification (I have heard that the original GEMSTART won't work with the new ROMs.) If you want to try something rather humorous, write a DA that Pexec's a GEM program as soon as it runs. The application runs normally, puts up its menu bar and all, but as soon as it does an evnt_multi the desktop magically takes-over control once again which, of course, leads to several bombs if you get tired of watching disk drive windows pop up from nowhere when you click on the desktop and decide to select a menu item. Thanks in advance! --------------------------------------------------------------------------- EEEeek! I went against my own Dan Wilga credo and used a :-) !!! AndOr@UMASS.Bitnet I'm so ashamed... Arpa? Just try and figure it out!
dclemans@mntgfx.mentor.com (Dave Clemans) (02/04/88)
Re: Control C GEMDOS doesn't directly terminate a process when it sees a Control-C character in a "cooked" input function; instead it calls a special pseudo-interrupt vector called the critical exception handler. The default code for that handler is what terminates the process. If you install a replacement for it you can do whatever you want. If I remember correctly this is described in the Atari GEMDOS Users Guide manual. Re: autostarting GEM programs My understanding is that what the autostart programs do is to set up a small TSR routine attached to the vertical blank interrupt vector. On each interrupt the code looks around and tries to guess whether or not GEM is initialized yet. If it looks initialized it disengages from the vertical blank interrupt and starts the requested GEM program. Whether or not a specific version of this technique works with all versions of the ROM's depends on specifically how the code checks for GEM being initialized. dgc
apratt@atari.UUCP (Allan Pratt) (02/05/88)
in article <1988Feb3.080736.14303@mntgfx.mentor.com>, dclemans@mntgfx.mentor.com (Dave Clemans) says: > Re: Control C > GEMDOS doesn't directly terminate a process when it sees a Control-C character > in a "cooked" input function; instead it calls a special pseudo-interrupt > vector called the critical exception handler. The default code for that > handler is what terminates the process. If you install a replacement for it > you can do whatever you want. If I remember correctly this is described > in the Atari GEMDOS Users Guide manual. Not exactly. First, GEMDOS calls the "terminate vector" not the "critical exception handler." Second, that vector points by default an RTS instruction. It is the code after the call which terminates the process. This vector gets called when you use Pterm(), too: it's not strictly a "control C" handler. You can avoid being terminated by doing a "setjmp(term_buf)" where you want to recover, and setting this vector to point to something like "longjmp(term_buf,1)" Unfortunately, there isn't a lot of documentation on this, and other projects prevent me from going into more detail. ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
tainter@ihlpg.ATT.COM (Tainter) (02/12/88)
In article <971@atari.UUCP>, apratt@atari.UUCP (Allan Pratt) writes: > in article <1988Feb3.080736.14303@mntgfx.mentor.com>, > dclemans@mntgfx.mentor.com (Dave Clemans) says: > > Re: Control C > Not exactly. First, GEMDOS calls the "terminate vector" not the > "critical exception handler." Second, that vector points by default an > RTS instruction. It is the code after the call which terminates the > process. > This vector gets called when you use Pterm(), too: it's not strictly a > "control C" handler. This last bit makes it worthless, unless you can tell us how to tell if we are getting a ^C or a Pterm(). Of course, ^C still isn't worth much even so since it is not an interrupt but a polled event (polled by calls to the gemdos cooked routines) but it would be worth something then. > Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. --j.a.tainter
apratt@atari.UUCP (Allan Pratt) (02/17/88)
in article <4803@ihlpg.ATT.COM>, tainter@ihlpg.ATT.COM (Tainter) says: >> This vector gets called when you use Pterm(), too: it's not strictly a >> "control C" handler. > > This last bit makes it worthless, unless you can tell us how to tell if > we are getting a ^C or a Pterm(). > --j.a.tainter You're getting a Pterm if you call Pterm, and you're getting ^C if you don't. If you know you're calling Pterm, then call your clean-up routine on your own and un-install it before you terminate. Also un-install your terminate vector before you Pexec: you can tell what the result of the Pexec was by the return code: -32L means the child terminated with ^C. Any other LONG negative value means the Pexec failed, and any LONG positive value (i.e. (x & 0xffff0000) == 0) means it called Pterm(x). Please don't shoot words like "worthless" around unqualified. ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
david@bdt.UUCP (David Beckemeyer) (02/19/88)
In article <980@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >You're getting a Pterm if you call Pterm, and you're getting ^C if you >don't. If you know you're calling Pterm, then call your clean-up >routine on your own and un-install it before you terminate. > This isn't entirely true. An exception can also produce a Pterm. So an exception would look like a ^C, based on the above test. The only way around this is to install your own exception handlers, which isn't too clean either, if you ask me (but who did, right?). -- David Beckemeyer | "To understand ranch lingo all yuh Beckemeyer Development Tools | have to do is to know in advance what 478 Santa Clara Ave, Oakland, CA 94610 | the other feller means an' then pay UUCP: ...!ihnp4!hoptoad!bdt!david | no attention to what he says"
apratt@atari.UUCP (Allan Pratt) (02/23/88)
in article <142@bdt.UUCP>, david@bdt.UUCP (David Beckemeyer) says: > > In article <980@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >>You're getting a Pterm if you call Pterm, and you're getting ^C if you >>don't. If you know you're calling Pterm, then call your clean-up >>routine on your own and un-install it before you terminate. >> > This isn't entirely true. An exception can also produce a Pterm. Sorry, of course that's right. The bomb handler does a Pterm to try to kill the offending process. But why would you want to handle bombs any differently from ^C? (Besides, correct programs don't produce bombs! :-) ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
steven@cwi.nl (Steven Pemberton) (02/26/88)
In article <986@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: > But why would you want to handle bombs any differently from ^C? > (Besides, correct programs don't produce bombs! :-) Well, if you're writing an interpreter for a programming language, you want ^C to interrupt the running interpreted program, but not the interpreter itself. On the other hand, you want a bomb to kill the interpreter. Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
apratt@atari.UUCP (Allan Pratt) (03/01/88)
From article <217@piring.cwi.nl>, by steven@cwi.nl (Steven Pemberton): > In article <986@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >> But why would you want to handle bombs any differently from ^C? >> (Besides, correct programs don't produce bombs! :-) > > Well, if you're writing an interpreter for a programming language, you > want ^C to interrupt the running interpreted program, but not the > interpreter itself. On the other hand, you want a bomb to kill the > interpreter. > > Steven Pemberton, CWI, Amsterdam; steven@cwi.nl No you don't... You want a bomb to kill the running program, back to the interpreter, so the programmer can correct the problem. Or, you should install your own bomb handler (as most interpreters better than ST BASIC do). ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
david@bdt.UUCP (David Beckemeyer) (03/04/88)
Since this discussion hasn't ended yet, I thought I'd bring up a few gotcha's regarding writing your own ^C and bomb handlers. GEMDOS calls the Pterm handler with all files open, and it could happen at any instant in the code. Consider a recursive File Tree scanner that uses Fsetdta() and Fsfirst/Fsnext: scan(pattern, mask) char *patter; int mask; { DMABUFFER dbuf, *olddma; /* remember callers DTA buffer */ olddma = Fgetdta(); /* Set DTA buffer for this scan */ Fsetdma(dbuf); if (Fsfirst(pattern, mask) == 0) { do { /* see if found a directory */ if (isdirectory(dbuf)) scan(pattern, mask); else /* process file */ } while (Fsnext() == 0); } /* reset DTA */ Fsetdta(olddma); } If a bomb or ^C occurs at recursion level N, the dta pointer points to memory on the stack (the auto dbuf variable). Clearly there are potential problems here. What happens to the stack? How can the handler fix-up the stack? A long-jump? But then what happens in the above case where now the DTA points to a place that will be used again for new stack space. Open files also remain open when the Pterm is called, so these must also be cleaned up. My point is: don't be mislead into thinking that a Pterm handler is nothing more than a simple longjump. -- David Beckemeyer | "To understand ranch lingo all yuh Beckemeyer Development Tools | have to do is to know in advance what 478 Santa Clara Ave, Oakland, CA 94610 | the other feller means an' then pay UUCP: ...!ihnp4!hoptoad!bdt!david | no attention to what he says"
apratt@atari.UUCP (Allan Pratt) (03/08/88)
From article <167@bdt.UUCP>, by david@bdt.UUCP (David Beckemeyer): > What happens to the stack? How can the > handler fix-up the stack? A long-jump? But then what happens in > the above case where now the DTA points to a place that will be used > again for new stack space. > > Open files also remain open when the Pterm is called, so these must > also be cleaned up. > > My point is: don't be mislead into thinking that a Pterm handler is > nothing more than a simple longjump. It *is* just a simple longjmp! (Except that it gets executed in Super mode -- but the handler can just consist of a longjmp.) If you have a global pointer (like an extern or your DTA) pointing into your stack, and you do a longjmp, it still points to your stack (or where the stack will someday be). It's up to you not to use those pointers -- in the case where the ^C might occur while the DTA is on the stack, your Pterm-recovery routine should reset the DTA to somewhere else. On the other hand, since the DTA is only used for Fsfirst/Fsnext, you should explicitly set it before each round of calls. Then you're sure to be safe from DTA fever. Other globals have always had that problem, though: if you longjmp, you have to be sure you reinitialize them. ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
david@bdt.UUCP (David Beckemeyer) (03/15/88)
In article <1008@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >It *is* just a simple longjmp! (Except that it gets executed in Super >mode -- but the handler can just consist of a longjmp.) If you have a... If the Pterm handler consists of just a longjmp, doesn't that mean that the supervisor stack is permanently shrinking, and that the program thereafter runs in supervisor mode, even if it was started in user mode? Wouldn't that mean that a lot (maybe not so many) ^C's would use up all the supervisor stack? Also what about open files? SOmebody has to take care of them don't they? If the program re-opens the same files, things could get messy (one problem is the great duplicate file name thing). >Other globals have always had that problem, though: if you longjmp, >you have to be sure you reinitialize them. This statement alone (along with others in your message) suggest that the Pterm handler is more than just a longjmp. I still contend that the Pterm handler must "clean up whatever needs cleaning up, and then longjmp". The list of "whatever needs cleaning up" is where things can get complicated (potentially). -- David Beckemeyer | "To understand ranch lingo all yuh Beckemeyer Development Tools | have to do is to know in advance what 478 Santa Clara Ave, Oakland, CA 94610 | the other feller means an' then pay UUCP: ...!ihnp4!hoptoad!bdt!david | no attention to what he says"
apratt@atari.UUCP (Allan Pratt) (03/18/88)
From article <176@bdt.UUCP>, by david@bdt.UUCP (David Beckemeyer): > In article <1008@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >>It *is* just a simple longjmp! (Except that it gets executed in Super >>mode -- but the handler can just consist of a longjmp.) If you have a... > > If the Pterm handler consists of just a longjmp, doesn't that mean that the > supervisor stack is permanently shrinking, and that the program thereafter > runs in supervisor mode, even if it was started in user mode? Wouldn't > that mean that a lot (maybe not so many) ^C's would use up all the supervisor > stack? You misunderstand me. By "Pterm handler" I meant the thing YOU might install to catch bombs, Pterm's, and ^C's yourself. *Of course* Pterm is more complicated than that in Gemdos: it has to free your memory, close your files, and so on. If you want to execute some procedure (like removing your vblank routine) when you get ^C, bombs, or Pterm, you should install the address of that procedure as the terminate vector. When Pterm gets hit (for any of these reasons), your handler will get called (via jsr, in super mode), and when it returns, the Pterm continues and terminates the process. This is what Sid does when it says "Bye!" -- that's the terminate handler talking. If you are a shell and you want to return to your command prompt when the user hits ^C, you have to be a little more clever: you make the terminate vector point to a routine which does a go-to-user-mode-and-longjmp operation. The target of the longjmp is responsible for recovering from the problem. Simply put, it could look like this: #include <osbind.h> #include <longjmp.h> jmp_buf err_buf; long old_terminate_value; main_loop() { char cmdbuf[258]; int terminate_handler(); old_terminate_value = Setexc(0x102,terminate_handler); if (setjmp(err_buf)) { /* this code is target of longjmp */ Cconws("*Break*\r\n"); } /* normal flow and longjmp both end up here */ cmdbuf[0] = 255; while (1) { Cconws(prompt_string); Cconrs(cmdbuf); cmdbuf[cmdbuf[1]+2] = 0; /* null-terminate the string */ do_cmdline(&cmdbuf[2]); } } terminate_handler() { longjmp(err_buf,-1); } exit_command() { Setexc(0x102,old_terminate_value); Pterm(0); } The above fragments assume that setjmp saves the SR of the caller and restores it for the longjmp... This is a nontrivial thing to do because you can't just use RTE from user mode. The exit_command fragment is here to show that you have to UN-install the vector before you Pterm, because otherwise it'll just get hit again. Does this make anything more clear? ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
david@bdt.UUCP (David Beckemeyer) (03/22/88)
In article <1018@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >You misunderstand me. By "Pterm handler" I meant the thing YOU might >install to catch bombs, Pterm's, and ^C's yourself. *Of course* Pterm >is more complicated than that in Gemdos: it has to free your memory, >close your files, and so on. No you misunderstand me. I know exactly what a Pterm handler is. I posted my original message not to help you, Allan, (I know you know what they should do), but to help others. Somebody originally stated that the Pterm (^C 0x102 vector) could just be a longjmp. And all I was trying to say was that it was a little bit more than this, and gave a definition of "clean up and then longjmp". Then you posted an excellent example of a Pterm/^C handler that demonstrates how you do exactly that (clean up and then longjmp). Where "clean up" depends on the application, and may be "null" in the degenerate case. The whole thing became a much longer discussion that it ever should have been. It's my fault for saying something, and not doing what you did and just give a good example. But to try and make my point one more time. All I'm trying to say is that there *are* cases, depending on the state of the application, where a simple longjmp, and no "clean up" (whether handled by the Pterm handler itself, or its target) will result in an upset system. -- David Beckemeyer | "To understand ranch lingo all yuh Beckemeyer Development Tools | have to do is to know in advance what 478 Santa Clara Ave, Oakland, CA 94610 | the other feller means an' then pay UUCP: ...!ihnp4!hoptoad!bdt!david | no attention to what he says"