cpp@cci632.UUCP (Carl P. Petito) (09/03/90)
I have a program that I would like to be able to terminate from the keyboard. QC2.5 has an example using 'signal' that I used; however, it appears that the only time ^C is effective is when the program is doing i/o to the console. To confirm this, I modified the example program as shown below, and I found that if I hit ^C nothing happens until the string starts to print; I get the first two characters followed by ^C. What's worse, if output is redirected to a file, ^C doesn't do anything while the program is running. What am I doing wrong? Any pointers would be appreciated. By the the way I'm using MS-DOS 3.3. Carl Petito #include <stdio.h> #include <conio.h> #include <signal.h> #include <process.h> #include <setjmp.h> #include <stdlib.h> #include <float.h> #include <dos.h> #include <bios.h> void ctrlchandler( void ); /* Prototypes */ void safeout( char *str ); int safein( void ); void main() { long i; /* Modify CTRL+C behavior. */ if( signal( SIGINT, ctrlchandler ) == SIG_ERR ) { fprintf( stderr, "Couldn't set SIGINT\n" ); abort(); } /* loop illustrates results. */ for (i = 0; i < 999999l; i++) ; printf("First loop done\n"); for (i = 0; i < 999999l; i++) ; printf("Second loop done\n"); } /* Handles SIGINT (CTRL+C) interrupt. */ void ctrlchandler() { int ch; /* Disallow CTRL+C during handler. */ signal( SIGINT, SIG_IGN ); safeout( "Abort processing? " ); ch = safein(); safeout( "\r\n" ); if( (ch == 'y') || (ch == 'Y') ) abort(); else /* The CTRL+C interrupt must be reset to our handler since by * default it is reset to the system handler. */ signal( SIGINT, ctrlchandler ); } /* Outputs a string using system level calls. */ void safeout( char *str ) { union REGS inregs, outregs; inregs.h.ah = 0x0e; while( *str ) { inregs.h.al = *str++; int86( 0x10, &inregs, &outregs ); } } /* Inputs a character using system level calls. */ int safein() { return (_bios_keybrd( _KEYBRD_READ ) & 0xff ); }
mitchell (Bill Mitchell) (09/04/90)
In article <39616@cci632.UUCP> cpp@cci632.UUCP (Carl P. Petito) writes: >I have a program that I would like to be able to terminate from the >keyboard. QC2.5 has an example using 'signal' that I used; however, it appears >that the only time ^C is effective is when the program is doing i/o to >the console. To confirm this, I modified the example program as shown >below, and I found that if I hit ^C nothing happens until the string >starts to print; I get the first two characters followed by ^C. >What's worse, if output is redirected to a file, ^C doesn't do anything >while the program is running. What am I doing wrong? Any pointers would >be appreciated. By the the way I'm using MS-DOS 3.3. > I'm replying with remembered info without checking it out. Sorry, but this may help. I recall from examining the bios listings in the IBM tech ref manual that ctrl-brk recognition is done as raw scan codes are extracted from the typeahead buffer. You might want to look at that for details. Also, placing a line containing the words "break on" in your autoexec.bat file will, I think, get this interpretation made whenever disk I/O is in progress. SIGINT should then work whenever the program hangs a read for the keyboard or for a disk. Won't help if your program is in a compute-bound loop, but better than nothing. Hope this helps.
browns@iccgcc.decnet.ab.com (Stan Brown, Oak Road Systems) (09/05/90)
In article <39616@cci632.UUCP>, cpp@cci632.UUCP (Carl P. Petito) writes: > I have a program that I would like to be able to terminate from the > keyboard. QC2.5 has an example using 'signal' that I used; however, it appears > that the only time ^C is effective is when the program is doing i/o to > the console. [detailed description omitted] Carl, this is probably related to a missing BREAK command. Before running your program, at the DOS prompt type BREAK You'll probably see "BREAK is off". This means that the only time DOS is monitoring for ^C is during console and printer I/O. (There may be one or two other instances.) If you type the command BREAK ON and then run your program, you should be able to interrupt it with ^C at any time. Note: ^C and ^Break are not quite the same. If you have a running program and type keystrokes into the keyboard buffer, ^C won't get processed until after those keystrokes. However, ^Break gets processed right away (if BREAK is on) even if there are unused keystrokes in the input buffer. It seems strange that this should be so, since the manuals talk about them as interchangeable, but the above has been my experience. (Also, the ^Break or Ctrl-Break combination may be obtained by pressing and holding the Ctrl key, then pressing ScrollLock, then releasing both keys. Depends on your keyboard.) Check your DOS manual for the exact format of BREAK command in CONFIG.SYS. In AUTOEXEC.BAT, it's the same as at the command prompt. Stan Brown, Oak Road Systems, Cleveland, Ohio, U.S.A. (216) 371-0043 The opinions expressed are mine. Mine alone! Nobody else is responsible for them or even endorses them--except my cat Dexter, and he signed the power of attorney only under my threat to cut off his Cat Chow!