[comp.unix.questions] catching signals while writing to a tty-line

aiv@euraiv1.UUCP (Eelco van Asperen) (09/03/87)

Hi, I have a problem regarding the use of alarm() in combination with
writing to a tty-line. The tty-line is put in raw-mode and write() is
used to send data; I would like to use alarm() to detect timeouts and
warn the user of my program of this event. After displaying this warning, 
the program should continue sending data. Now, upon reading the man-page 
for signal() it said: 

	"when a signal that is to be caught occurs during a read, a write,
	an open, or an ioctl system call on a slow device (like a terminal;
	but not a file), during a pause system call, or during a wait system
	call that does not return immediately due to the existence of a 
	previously stopped or zombie process, the signal catching function
	will be executed and the interrupted system call will return -1 to
	the calling process with errno set to EINTR."

(btw, I use System V release 2.0 on an AT&T 3B2/300)

The problem is of course to detect the number of characters that has
already been written so that we don't send chars twice or not at all.

Thanks in advance for the brain-cycles you use to answer my question,

Eelco van Asperen.

-----------------------------------------+------------------------------
Erasmus University Rotterdam             |uucp:mcvax!eurifb!euraiv1!evas
Fac. of Economics, Computer Science Dept.|earn:asperen@hroeur5
PO.box  1738 / 3000 DR  Rotterdam        |       
T H E    N E T H E R L A N D S           |Yet Another Silly Signature.
-----------------------------------------+------------------------------

gwyn@brl-smoke.ARPA (Doug Gwyn ) (09/04/87)

In article <589@euraiv1.UUCP> aiv@euraiv1.UUCP (Eelco van Asperen) writes:
>	the calling process with errno set to EINTR."
>The problem is of course to detect the number of characters that has
>already been written so that we don't send chars twice or not at all.

You can't.  It's a serious design botch.

4.nBSD (n >= 2) has the opposite problem: it restarts the interrupted
I/O so some characters are transmitted twice (and you can't tell how
many).

This is one of those things that could have been fixed in IEEE 1003.1
(POSIX), without hurting any application (how could it hurt to get
correct information in such a case?).  However, as of Draft 11, POSIX
has waffled on this, allowing either -1 (EINTR) or correct byte count
for the partial transfer to be returned.  This is the sort of thing
that I find unacceptable in a STANDARD.  It undoubtedly arose because
some vendor thinks that their POSIX-compatible write() will have to
be backward-compatible with their current broken write(); of course
both old and new behavior could be provided by vendors who have this
concern, but either that hasn't occurred to them, or else they would
rather have a serious semantic botch than do the work necessary to
fix it.  I am disgusted by this.

guy%gorodish@Sun.COM (Guy Harris) (09/04/87)

> The problem is of course to detect the number of characters that has
> already been written so that we don't send chars twice or not at all.

It can't be done.  If you had S5R3 you could hold off the signal while you're
writing, but I infer from your description that the whole point of the signal
*is* to interrupt the "write".

4BSD restartable system calls won't help, either, as only "write"s that have
written nothing are restarted; if the "write" has transferred data, it is
interrupted in the standard UNIX fashion.

The current IEEE POSIX draft specifies that an implementation *may* make
"write" return the number of bytes written if it is interrupted after having
transferred some data; however, it does not require this.  Some implementations
may provide this, but I don't know if any do now.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

rml@hpfcdc.HP.COM (Bob Lenk) (09/05/87)

> >	the calling process with errno set to EINTR."
> >The problem is of course to detect the number of characters that has
> >already been written so that we don't send chars twice or not at all.
> 
> You can't.  It's a serious design botch.

I'll agree with the first statement and 90% with the second.

> This is one of those things that could have been fixed in IEEE 1003.1

Well it was for a while, but was then "unfixed".  Unfortunately, it is
not possible with all hardware to tell precisely how much has been
written, especially in situations where there is buffering on the
interface and/or the device.  Thus the standard couldn't reasonably
require a correct count to be returned.  While many of us wanted to
require "the best data possible," there didn't seem to be a good way
to say that.  Thus the folks who wanted to keep returning no useful
data got their wish.  If anyone can come up with a better solution,
I'm willing to help push for it (of course I can't guarantee success).

Back to the original question, the best you can do is do all one-byte
writes (at the write(2) level).  That way you can be relatively (but
not absolutely) sure that no bytes have been transferred on an EINTR.

		Bob Lenk
		{ihnp4, hplabs}!hpfcla!rml

mpl@sfsup.UUCP (M.P.Lindner) (09/10/87)

In article <589@euraiv1.UUCP>, aiv@euraiv1.UUCP writes:
> 	"when a signal that is to be caught occurs during a read, a write,
	...
> 	will be executed and the interrupted system call will return -1 to
> 	the calling process with errno set to EINTR."
> 
> (btw, I use System V release 2.0 on an AT&T 3B2/300)
> 
> The problem is of course to detect the number of characters that has
> already been written so that we don't send chars twice or not at all.
> 
> Eelco van Asperen.

Previous versions of UNIX(R) behaved as you'd like it to - write returned the
number of characters actually written.  However, in System V UNIX, the
behaviour was modified to return -1.  Consider that write *should* return -1
*on an error*.  It seems that a signal you're expecting is now considered
an error!

As for a solution, there is none, other than to modify the kernel.  This
behaviour broke some of my programs and several applications I know of.
It doesn't happen on *all* implementations of system V yet, but it will.

Call your support rep and complain.  I think this is something that should
be changed back, but heck, I only *work* on UNIX, so they won't listen to
me :{).

Mike Lindner
Disclaimer:  The above opinions are contrary to those of my employer!

guy@sun.uucp (Guy Harris) (09/11/87)

> Previous versions of UNIX(R) behaved as you'd like it to - write returned
> the number of characters actually written.

Are you certain that *all* versions prior to S5 did this?  I am not aware of
any commonly distributed versions that did; V6 returned -1 and set "errno" to
EINTR, as did V7 (and thus 4BSD, at least if any data had actually been
transferred), as did System III.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)