[comp.sys.ibm.pc] DOS Critical-error handler

dragheb@isis.UUCP (Darius "OPRDRT" Ragheb) (07/13/87)

I am currently writing a section of code to backup large files from
a fixed disk to floppys (the typical size of a file being greater than
2 Meg.)  I want to trap the Abort, Retry, Ignore message (which
is int 24h...right?) but have been completely unsuccesful.  I have
replaced interrupt vectors before, so i figured this was the same
as the others.....

I would appreciate any help (please send e-mail....I will post
results if there is interest).

everett@hpcvlo.HP.COM (Everett Kaser) (07/22/87)

This is a code fragment that I used in a recent program.  It seems to do the
job.  The effect is that the Abort, Retry, or Ignore message is suppressed,
and the application receives a CY flag set upon return from the function call
to indicate an error occurred during the call.

;
; call INIT during program initialization to take over int vector
;
init:
	push	ds
	cli
	xor	bx,bx
	mov	ds,bx			; point data segment to vector table
	mov	di,4*24h		; point to critical error int vector
	mov	cx,[di]			; get old vector
	mov	dx,[di+2]
	mov	word ptr [di],offset criterr	; set vector to our routine
	mov	[di+2],cs
	sti
	pop	ds
	mov	savint24off,cx		; save old vector
	mov	savint24seg,dx
	ret
;
; call UN_INIT before exiting program to restore int vector (may not be
;  necessary, since I think DOS restores the vector when a program terminates).
;
un_init:
	mov	ax,savint24off
	mov	bx,savint24seg
	push	ds
	xor	di,di
	mov	ds,di
	mov	di,4*24h
	cli
	mov	[di],ax
	mov	[di+2],bx
	sti
	pop	ds
	ret
;
; actual critical error handling routine.  can be far more complex, but this
; should suffice to keep the Abort, Retry, or Ignore message from appearing.
;
criterr	proc	far
	mov	al,0			; tell DOS to ignore error, but return
ctrlc:					; the CY flag set so application
	iret				; knows an error occurred
criterr	endp
;
savint24off	dw	?
savint24seg	dw	?
;

Hope this helps.

Everett Kaser
Hewlett-Packard Co.
Corvallis, OR

dhesi@bsu-cs.UUCP (Rahul Dhesi) (07/23/87)

In article <1610020@hpcvlo.HP.COM> everett@hpcvlo.HP.COM (Everett Kaser) writes:
>This is a code fragment that I used in a recent program.  It seems to do the
>job. 
[code fragment that fools around with interrupt vectors]

The code fragment provided in the quoted article directly manipulates
the interrupt vectors in low memory.  Please don't do this.  But if you
must, please don't ask others to do this!  User applications have no
business bypassing the standard operating system-provided interfaces.
MS-DOS provides system calls that let you change the address of the
critical error handler.  These should be used.
-- 
Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi

nathan@eddie.MIT.EDU (Nathan Glasser) (07/25/87)

In article <1610020@hpcvlo.HP.COM> everett@hpcvlo.HP.COM (Everett Kaser) writes:
>This is a code fragment that I used in a recent program.  It seems to do the
>job.  The effect is that the Abort, Retry, or Ignore message is suppressed,
>and the application receives a CY flag set upon return from the function call
>to indicate an error occurred during the call.
>
>; actual critical error handling routine.  can be far more complex, but this
>; should suffice to keep the Abort, Retry, or Ignore message from appearing.
>;
>criterr	proc	far
>	mov	al,0			; tell DOS to ignore error, but return
>ctrlc:					; the CY flag set so application
>	iret				; knows an error occurred
>criterr	endp

Returning 0 in al is documented as telling dos to ignore the error,
while returning 3 is documented as aborted the system call in progress.
The documentation also warns returning 0 will cause dos to think
the call was successful, and may cause various problems.

The other day, in fact, I was setting this stuff up by myself, and
I decided to return 3 after doing some testing. It seems that it may
be random whether the carry flag is set when returning 0 (am not sure).
It always seems to return the carry flag if you use 3.

E.g. when using a Lattice C program, a read is apparently successful
(at least sometimes) if I return 0, but never is if I return 3.
The read will end up putting garbage in your buffer in the former case.
-- 
				Nathan Glasser
				nathan@mit-eddie.uucp (usenet)
fnord				nathan@xx.lcs.mit.edu (arpa)
"A tribble is the only love that money can buy."

nathan@eddie.MIT.EDU (Nathan Glasser) (07/25/87)

In article <872@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>The code fragment provided in the quoted article directly manipulates
>the interrupt vectors in low memory.  Please don't do this.  But if you
>must, please don't ask others to do this!  User applications have no
>business bypassing the standard operating system-provided interfaces.
>MS-DOS provides system calls that let you change the address of the
>critical error handler.  These should be used.

True, there are Dos system calls to do this, but the interrupt vectors
have nothing to do with Dos. They are hardware (8086/8088/80286) specific.
You referred to the Dos methed as "the standard operating system-provided
interfaces," whereas it is not really the case.

Maybe if Dos were written better, and if nobody ever did anything
with the bios or hardware directly, people wouldn't have started doing
this. There are many things a programmer might want to do which are
supported, say, by the bios, for which Dos provides no interface. The
interrupt vectors are one area where Dos does provide an interface.
But since everybody knows that all it does is turn off interrupts (cli)
do the same mov instructions as given in the critical handler
article, and turn them back on (sti), and it is more efficient
to do this directly than doing the Dos function call, people just
do it directly.

In addition, one fact which people don't usually have to think
about but is sometimes important is that some/all? calls to Dos
functions turn on interrupts (sti) at some point before doing
whatever it is they're supposed to do. If your program needs
to leave interrupts turned off for a period of time during which
we also want to set a vector, you can't use the Dos function call.
(I ran into this the other day. It was really tough to find.)
-- 
				Nathan Glasser
				nathan@mit-eddie.uucp (usenet)
fnord				nathan@xx.lcs.mit.edu (arpa)
"A tribble is the only love that money can buy."

null@bsu-cs.UUCP (Patrick Bennett) (07/25/87)

In article <6381@eddie.MIT.EDU>, nathan@eddie.MIT.EDU (Nathan Glasser) writes:
> In addition, one fact which people don't usually have to think
> about but is sometimes important is that some/all? calls to Dos
> functions turn on interrupts (sti) at some point before doing
> whatever it is they're supposed to do. If your program needs
                                                         ^^^^^ <ACK!>
> to leave interrupts turned off for a period of time during which
> we also want to set a vector, you can't use the Dos function call.
> (I ran into this the other day. It was really tough to find.)

Interrupts should ALWAYS be disabled when manipulating interrupt vectors - 
If interrupts were enabled, one could be called just before you finish
updating the interrupt vector with the new address - eg. only the segment
address has been changed.  Well, what if the interrupt you're changing
were called?  It would have a correct segment address, but the offset would
place it in the twilight zone...  Common fumble with the timer tick vector...

No no no no no no - definitely clear those interrupts!

-- 
----
Patrick Bennett     UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!null

nathan@eddie.MIT.EDU (Nathan Glasser) (07/26/87)

In article <888@bsu-cs.UUCP> null@bsu-cs.UUCP (Patrick Bennett) writes:
>In article <6381@eddie.MIT.EDU>, nathan@eddie.MIT.EDU (Nathan Glasser) writes:
>> In addition, one fact which people don't usually have to think
>> about but is sometimes important is that some/all? calls to Dos
>> functions turn on interrupts (sti) at some point before doing
>> whatever it is they're supposed to do. If your program needs
>                                                         ^^^^^ <ACK!>
>> to leave interrupts turned off for a period of time during which
>> we also want to set a vector, you can't use the Dos function call.
>Interrupts should ALWAYS be disabled when manipulating interrupt vectors - 
>If interrupts were enabled, one could be called just before you finish
>updating the interrupt vector with the new address - eg. only the segment
>address has been changed.  Well, what if the interrupt you're changing
>were called?  It would have a correct segment address, but the offset would
>place it in the twilight zone...  Common fumble with the timer tick vector...

Thanks alot for misunderstanding me.
I stated early in the quoted article:

(referring to dos interrupt handler setting function)
But since everybody knows that all it does is turn off interrupts (cli)
do the same mov instructions as given in the critical handler
article, and turn them back on (sti), and it is more efficient
to do this directly than doing the Dos function call, people just
do it directly.

I will give you some more information that might help you understand
what I meant in the paragraph of mine that you quoted and decided
was incorrect.

Suppose you are writing some code in which you want interrupts to
be off from point A in the code to point B in the code. Somewhere
in between A and B we just happen to want to set an interrupt vector.
If we use the Dos function call to do this, we will screw ourselves
up, because some/all of the Dos functions turn interrupts at some
point. I have not verified it for this one, but I have seen it
do it for others for which there is no need to turn them on. Thus
the only safe way to do it here is to not use the Dos function.

Is this clear?
-- 
				Nathan Glasser
				nathan@mit-eddie.uucp (usenet)
fnord				nathan@xx.lcs.mit.edu (arpa)
"A tribble is the only love that money can buy."

jack@csccat.UUCP (Jack Hudler) (07/26/87)

Here is my Idea of a Critical Error Handler. It sets carry for the
int 21 caller and sets the return in AX to 100..10C for the caller to know
that a hard error occured.

INTERRUPT_24	PROC	FAR
		ADD	SP,6			; Dump Dos Return
		MOV	BP,SP
		OR	BYTE PTR[BP+22],1	; Set Returning Carry
		TEST	AH,AH			; Where testing the high bit
		MOV	AX,99			; Return 99 if Non-Disk Error
		JS	INT14a			; Jump if NOT disk error
		MOV	AX,DI			; Setup Return
		ADD	AX,100			; Add 100 to Error Code
INT24a:		POP	BX
		POP	BX
		POP	CX
		POP	DX
		POP	SI
		POP	DI
		POP	BP
		POP	DS
		POP	ES
		IRET		; Return to INT 21 Caller directly
INTERRUPT_24	ENP



-- 
See above 	 (214)661-8960

everett@hpcvlo.HP.COM (Everett Kaser) (08/01/87)

>Here is my Idea of a Critical Error Handler. It sets carry for the
>int 21 caller and sets the return in AX to 100..10C for the caller to know
>that a hard error occured.
>
>INTERRUPT_24	PROC	FAR
>		ADD	SP,6			; Dump Dos Return
>		MOV	BP,SP

Something you should be aware of is that if you bail out of the critical
error interrupt this way, (i.e. you're not returning back through DOS) you're
leaving DOS in an unstable state.  When this happens, the next call to DOS
must be a call below (I think) about 0ch. (i.e. one of the simple console I/O
routines, such as check for key.)  If not, if you try doing disk I/O or
something immediately after this bail-out, DOS will be confused as to what
state it's in, and you may get very unwanted behaviour.

Everett Kaser
Hewlett-Packard Co.
Corvallis, OR

ayac071@ut-ngp.UUCP (William T. Douglass) (08/04/87)

In article <1610024@hpcvlo.HP.COM> everett@hpcvlo.HP.COM (Everett Kaser) writes:
>Something you should be aware of is that if you bail out of the critical
>error interrupt this way, (i.e. you're not returning back through DOS) you're
>leaving DOS in an unstable state.  When this happens, the next call to DOS
>must be a call below (I think) about 0ch. (i.e. one of the simple console I/O
>routines, such as check for key.)  If not, if you try doing disk I/O or
>something immediately after this bail-out, DOS will be confused as to what
>state it's in, and you may get very unwanted behaviour.

Just out of curiosity, has anyone verified this?  I've read the warning the
the tech manual too, but I have written a critical error handler similar to
the one refered to above (returning without passing control back to DOS) and
implemented it on a menu-system written in Turbo Pascal.  After about a year
now, I've never hung or locked up (running on IBM AT's & XT'x, DOS 3.00 +).

Would anybody mail me if they have had such a problem as mentioned above. 
Thanks in advance.

Bill Douglass
ayac071@ngp.UUCP

jack@csccat.UUCP (Jack Hudler) (08/05/87)

In article <5795@ut-ngp.UUCP>, ayac071@ut-ngp.UUCP (William T. Douglass) writes:
> In article <1610024@hpcvlo.HP.COM> everett@hpcvlo.HP.COM (Everett Kaser) writes:
> >Something you should be aware of is that if you bail out of the critical
> >error interrupt this way, (i.e. you're not returning back through DOS) you're
> >leaving DOS in an unstable state.  When this happens, the next call to DOS
> 
> Just out of curiosity, has anyone verified this?  I've read the warning the
> the tech manual too, but I have written a critical error handler similar to
> the one refered to above (returning without passing control back to DOS) and
> I've never hung or locked up (running on IBM AT's & XT'x, DOS 3.00 +).

Do you thing that I would put any thing in our products that would leave
Dos in an unstable state. NO! :-)
We have ship 100's of thousands of copys of our software and not one problem
has ever been written up that could be something like dos being left in
an unstable state. In looking at old versions of our software we did issue a
reset disk command but if memory serves this use to be the case in DOS 1.0 or
2.0 but I think the people writing the manuals never bothered to take it out.
In any case we haven't seen it here.
-- 
See above 	 (214)661-8960