[comp.lang.c] XENIX <-> ULTRIX interrupts & traps

mike@samira.UUCP (Mike Deutsch) (11/10/86)

I have a program written in C which I need to run under both ULTRIX 1.2
on an 8600 and Microsoft sys V XENIX on an IBM AT.

In the application, the user enters commands from the keyboard.
I trap interrupts, and go to an interrupt handler when they hit
interrupt.  In this handler, I ask the user if they wish to continue
or abort.

Under XENIX, when the program returns from the interrupt handler, the
program doesn't still expect to be reading at the read where the interrupt
trap was received.  Under ULTRIX, it does.

1)  Which one is correct?  It's the same code, both C, so one must be wrong.

2)  I'd prefer the program to function as it does under XENIX.  How can
I get it to not continue with the read when there was an interrupt during
the read?

Thank you very much.

Please e-mail me the answer, as our net connection remains slightly
shaky.

ballou@brahms (Kenneth R. Ballou) (11/11/86)

In article <43@samira.UUCP> mike@samira.UUCP (Mike Deutsch) writes:
>I have a program written in C which I need to run under both ULTRIX 1.2
>on an 8600 and Microsoft sys V XENIX on an IBM AT.
>
>In the application, the user enters commands from the keyboard.
>I trap interrupts, and go to an interrupt handler when they hit
>interrupt.  In this handler, I ask the user if they wish to continue
>or abort.
>
>Under XENIX, when the program returns from the interrupt handler, the
>program doesn't still expect to be reading at the read where the interrupt
>trap was received.  Under ULTRIX, it does.
>
>1)  Which one is correct?  It's the same code, both C, so one must be wrong.

ABSOLUTELY NOT!  Library functions are exactly that:  library functions.
C does not specify how library functions must behave, or even what functions
must be provided in an implementation's library.

Now, if you browse through signal.h, you will note an error value called
EINTR.  At least on BSD 4.2, if a signal arrives while read is awaiting
data, read returns -1 and errno is set to EINTR:

     [EINTR]	    A read from	a slow device was interrupted
		    before any data arrived by the delivery of a
		    signal.

Again, please note that this is part of UNIX, not of C proper.

>2)  I'd prefer the program to function as it does under XENIX.  How can
>I get it to not continue with the read when there was an interrupt during
>the read?

Since read has returned -1, it seems you could examine the value of errno
and repeat the read call if errno is equal to EINTR, viz.:

	while (read (....) == -1 && errno == EINTR)
		;

Probably you will want to save the value returned by read for later use.

--------
Kenneth R. Ballou		...!ucbvax!brahms!ballou
Dept. of Mathematics		ballou@brahms.berkeley.EDU
University of California
Berkeley, California

guy@sun.uucp (Guy Harris) (11/12/86)

> >1)  Which one is correct?  It's the same code, both C, so one must be
> >    wrong.
> 
> ABSOLUTELY NOT!  Library functions are exactly that:  library functions.

Correct.

> C does not specify how library functions must behave, or even what functions
> must be provided in an implementation's library.

Correct, but not if you're talking about ANSI C.  It actually *does* specify
some functions that must be provided, and how they behave.  One of these
functions is "signal"; however, since "read" is (fortunately) not one of
these functions, it does not specify what happens to a "read" when you
return from a signal handler.

> Now, if you browse through signal.h, you will note an error value called
> EINTR.  At least on BSD 4.2, if a signal arrives while read is awaiting
> data, read returns -1 and errno is set to EINTR:

Well, not really; if you browse through "errno.h" you'll find EINTR, but you
sure won't find it in "signal.h".

More to the point, under *some* circumstances, on BSD 4.2 (which is what
ULTRIX-32, at least, is derived from; XENIX, however, does not derive its
signal handling code from BSD 4.2), returning from a signal handler to a
"read" will cause the "read" to return -1 and set "errno" to EINTR.
However, in the most common circumstances, it won't.  With the older signal
mechanism that V7, S3, and S5-derived systems, such as XENIX, provide,
returning from a signal handler to a "read" will cause the "read" to return
-1 and set "errno" to EINTR.

(Actually, it's a combination of the signal and "read" mechanisms, and I
think in the S5R3 "streams" code, if the signal handler returns to the
"read" *after it has already transferred some data* the "read" will return
the number of bytes it transferred before being interrupted.  This is what
the signal and "read" mechanisms should have done all along; otherwise, you
have no idea how much data was transferred before the interrupt occurred.)

With the newer 4.2BSD and 4.3BSD signal mechanisms, if the "read" has not
transferred any data, and the signal in question has not been specified as
interrupting system calls, returning from the signal handler will cause the
"read" to be reexecuted.  If the read has already transferred some data, or
if the 4.3BSD feature that permits you to specify that particular signals
should interrupt calls like "read" has been used, returning from the signal
handler will cause the "read" to return -1/EINTR, just as it does with older
signal mechanisms.

> >2)  I'd prefer the program to function as it does under XENIX.  How can
> >I get it to not continue with the read when there was an interrupt during
> >the read?
> 
> Since read has returned -1, it seems you could examine the value of errno
> and repeat the read call if errno is equal to EINTR, viz.:

Since "read" hasn't returned -1, but has been repeated for you by the
system, you can't.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

ballou@brahms (Kenneth R. Ballou) (11/13/86)

In article <9180@sun.uucp> guy@sun.UUCP writes:
[The next three lines are my stupid remark.  --- K. Ballou]
>> Now, if you browse through signal.h, you will note an error value called
>> EINTR.  At least on BSD 4.2, if a signal arrives while read is awaiting
>> data, read returns -1 and errno is set to EINTR:
>
>Well, not really; if you browse through "errno.h" you'll find EINTR, but you
>sure won't find it in "signal.h".

Quite right.  I was too busy fuming over what I had just read to check
my response carefully.  Sorry ...

--------
Kenneth R. Ballou		...!ucbvax!brahms!ballou
Dept. of Mathematics		ballou@brahms.berkeley.EDU
University of California
Berkeley, California  94720

caf@omen.UUCP (Chuck Forsberg WA7KGX) (11/13/86)

In article <43@samira.UUCP> mike@samira.UUCP (Mike Deutsch) writes:
:Under XENIX, when the program returns from the interrupt handler, the
:program doesn't still expect to be reading at the read where the interrupt
:trap was received.  Under ULTRIX, it does.
 ....
:2)  I'd prefer the program to function as it does under XENIX.  How can
:I get it to not continue with the read when there was an interrupt during
:the read?

A longjmp from within the interrupt handler should do the trick.  When 4.2 BSD
changed the way signals affected read calls, thus breaking rb/sb, I changed
the interrupt handler from the previous no-op (just let the read fail) to a
longjmp.  Just make sure the longjmp always has a valid place to long jump to!

Chuck Forsberg WA7KGX Author of Pro-YAM communications Tools for PCDOS and Unix
...!tektronix!reed!omen!caf  Omen Technology Inc "The High Reliability Software"
  Voice: 503-621-3406  17505-V Northwest Sauvie Island Road Portland OR 97231
TeleGodzilla BBS: 621-3746 2400/1200  CIS:70007,2304  Genie:CAF  Source:TCE022
  omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
  omen!/usr/spool/uucppublic/FILES lists all uucp-able files, updated hourly