[comp.unix.wizards] help needed on a unix system-call question

thssvhj@iitmax.IIT.EDU (vijay hemraj jadhwani) (03/06/89)

In my code I use a signal (SIGALRM), system-call, following which is a 'read'
system-call. The read is done on a tty-port. It is mentioned in the unix v
manual that 'read' will return -1 when interrupted by a signal. Is it poss-
ible to lose the partially read data by the 'read' system call, when the
signal was caught , even though I execute a 'read' again ? Note that I
am doing a 'read' on the tty-port. 

Thanks in advance for any help.

guy@auspex.UUCP (Guy Harris) (03/09/89)

>In my code I use a signal (SIGALRM), system-call, following which is a 'read'
>system-call. The read is done on a tty-port. It is mentioned in the unix v
>manual that 'read' will return -1 when interrupted by a signal. Is it poss-
>ible to lose the partially read data by the 'read' system call, when the
>signal was caught , even though I execute a 'read' again ? Note that I
>am doing a 'read' on the tty-port. 

Assuming by "is it possible to lose the partially read data" you mean
"if the 'read' blocks, and then transfers some data and blocks waiting
for more data, and *then* gets interrupted by a signal, is the data it
transferred more-or-less lost", the answer is "yes, and this happens
under 4.xBSD as well".  The problem is that, since you get a -1 back
from the "read", rather than a count of the number of bytes read, you
have no idea how much data was actually transferred. 

jcm@mtunb.ATT.COM (was-John McMillan) (03/10/89)

In article <1134@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>>In my code I use a signal (SIGALRM), system-call, following which is a 'read'
>>...
>...
>for more data, and *then* gets interrupted by a signal, is the data it
>transferred more-or-less lost", the answer is "yes, and this happens
>under 4.xBSD as well".  The problem is that, since you get a -1 back
>from the "read", rather than a count of the number of bytes read, you
>have no idea how much data was actually transferred. 

"More or less lost"?  "Unnoticed" may be more like it,
IF MY RECOLLECTIONS ARE CORRECT.  (When did that last occur?)
I can't RECALL any place for the characters to BE lost (in
traditional tty reads -- as opposed to STREAMS, which I've paid
little attention to), so I presume they're all in the user's buffer.

A workaround?  'Hate these -- will you still respect me in the morning?
(OK: neither do I.)

#define	BKGND	'\0'

SRead(f,b,l) char *b;		/* read args */
{	register	int i;
	register	char *c;
	extern		int	errno;

	errno = 0;	/* ZERO out the errno flag -- so it can be tested
			 *	after SRead() to detect interrupt IYGAD
			 */
	
			/* ZERO out the read buffer: its cheaper if you
			 *	know the dirty-bits -- ie., if you only
			 *	zap length of soiled bytes.
			 * OK: ZERO is 'NUL-ist' -- AA requires us to
			 *	give more-than-equal consideration to
			 *	other background chars.
			 */
	for ( i=l, c=b; i-- > 0; *c++ = BKGND);

			/* Only calculate kength when nec.
			 */
	if ( (i=read(f,b,l) < 0 ) )
			/* Back-Scanning vs. Forward-Scanning:
			 *	Wasted effort vs minimum of lost BKGNDs
			 */
		for ( c=b+l, i=l+1; --i > 0 && *--c == BKGND; );
	return i;
}
NB:
	It is a 30-second HACK.
	It is neither debugged nor fully general.
	It is far from optimized -- there are conflicting strategies.

The IDEA is that you can often infer the LENGTH of data if you can
"see" it against a known -- preferably un-receivable -- background.

There are multiple attacks and defenses for details of the above
implementation.  Someone must care about them: Wire Paladin, San Francisco.

jcm	-- juzz muttering

ka@june.cs.washington.edu (Kenneth Almquist) (03/11/89)

guy@auspex.UUCP (Guy Harris) writes:
> Assuming by "is it possible to lose the partially read data" you mean
> "if the 'read' blocks, and then transfers some data and blocks waiting
> for more data, and *then* gets interrupted by a signal, is the data it
> transferred more-or-less lost", the answer is "yes, and this happens
> under 4.xBSD as well".  The problem is that, since you get a -1 back
> from the "read", rather than a count of the number of bytes read, you
> have no idea how much data was actually transferred. 

I don't know of any cases where this should happen, at least on System V.
Reads on regular files, directories, disk devices and magnetic tapes are
not interruptable (assuming that the disk and tape device drivers don't do
nonstandard things).  Reads on a pipe will block until the pipe is nonempty
and then transfer what is in the pipe, so if a read on a pipe can only be
interrupted before any data is transferred.  Reads on cooked tty devices
block until an entire line is available and then copy in the entire line at
once.  I don't remember the raw tty device code as well, but I'm pretty
sure that in this case as well all the characters are buffered inside the
kernel and transferred to the user space in an uninterruptable operation
right before the read returns.

Write operations on a tty are different, since it is possible to write
more characters than the kernel is willing to buffer internally.  If the
write system call is interrupted after some but not all of the data has
been written, the kernel will return the number of characters written
rather than returning an error indication, so you can write out the rest
of the characters later.
				Kenneth Almquist

mouse@mcgill-vision.UUCP (der Mouse) (03/29/89)

In article <7553@june.cs.washington.edu>, ka@june.cs.washington.edu (Kenneth Almquist) writes:
> guy@auspex.UUCP (Guy Harris) writes:
>> Assuming by "is it possible to lose the partially read data" you
>> mean "if the 'read' blocks, and then transfers some data and blocks
>> waiting for more data, and *then* gets interrupted by a signal, is
>> the data it transferred more-or-less lost", the answer is "yes, and
>> [...]" [...].
> Reads on cooked tty devices block until an entire line is available
> and then copy in the entire line at once.

The original posting seems to have expired here.  There is one common
case which *looks* like "partially read" data being "lost", even though
this is not really true: when the signal coming in is due to a special
character (interrupt or quit, for example) being typed on the tty
that's being read from.  In this case, the input buffer is generally
flushed, losing any partial line that's been typed.  Until you realize
that the partial line is being buffered in the kernel and not
transferred to the user's buffer until you push return (and therefore
isn't partially read at all), this looks a lot like "losing partially
read data".

The original question probably belonged in comp.unix.questions, but we
all know nobody pays any attention to the distinction any longer :-(.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu