[comp.unix.wizards] xon/xoff, signals, hangup

guy@auspex.UUCP (Guy Harris) (11/17/88)

>When you close the line (e.g., at exit from SIGHUP), the kernel
>(correctly) waits for the output to drain.  It *should* give up
>after a `reasonable' timeout, on the assumption that output never
>will drain.

Define "reasonable".  What if the line is going to a printer, and it
runs out of paper?  It could be a while before those last few characters
get transmitted....

>A number of kernels get this wrong, various BSD implementations
>included.  Note, though, that `giving up' will put some terminals
>into a confused state.

The S5R3 streams code "gets it right" in the sense that it will time out
eventually; unfortunately, in addition to flushing data queued for a
streams module when it gets tired of waiting for that module to drain
its queue, it also gets rid of the module - which means that unless the
driver handles XON/XOFF, you lose flow control at some point, which
will, indeed, put some terminals in a confused state.

The line discipline-based S5 tty drivers don't time out, but they will
un-stop XOFFed output when the line is closed; this will also put some
terminals in a confused state....

Unfortunately, I'm not sure there's a single way of getting it right. 
Printers, plotters, etc. should be prepared to wait forever; terminals
on which people are logged in, or dial-out lines, should perhaps give up
eventually (although perhaps carrier going away could be the signal for
this).

chris@mimsy.UUCP (Chris Torek) (11/18/88)

>In article <14526@mimsy.UUCP> I wrote:
>>[The kernel] *should* give up after a `reasonable' timeout, on the
>>assumption that output never will drain.

In article <460@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>Define "reasonable".  What if the line is going to a printer, and it
>runs out of paper?  It could be a while before those last few characters
>get transmitted....

That is why I put the word in quotes.  Perhaps the timeout should be
configurable (say, `n' seconds, where 0 = wait forever, set by an ioctl).

Even waiting forever for a printer or plotter may be wrong: if one
uses XON/XOFF flow control, but is reset after an XOFF, it may never
send an XON.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

peter@ficc.uu.net (Peter da Silva) (11/19/88)

The basic problem here is that a process is only ever waiting on one
event at a time. This is so fundamental to UNIX that you don't ever
think about it... but there's really no reason why it has to be that
way.

Changing this would require a major change in how the kernel works, but
it'd be worth it in the long term. Realtime would become dead easy, for
example...

Here's an idea that would get you around this problem: when you send a signal
to a process, force a wakeup on whatever that process is waiting on. That
should make it pay attention to the signal and go on to die.
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation
"Have you hugged  U  your wolf today?"     uunet.uu.net!ficc!peter
Disclaimer: My typos are my own damn business.   peter@ficc.uu.net

chris@mimsy.UUCP (Chris Torek) (11/20/88)

In article <2269@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>The basic problem here is that a process is only ever waiting on one
>event at a time. This is so fundamental to UNIX that you don't ever
>think about it... but there's really no reason why it has to be that
>way.

Select() and, in SVR?, poll(), wait on multiple events, although they
do it somewhat by cheating.

>Here's an idea that would get you around this problem: when you send a signal
>to a process, force a wakeup on whatever that process is waiting on. That
>should make it pay attention to the signal and go on to die.

Not necessarily; indeed, the usual wait loop is something like

	while (resource->flag & LOCKED) {
		resource->flag |= WANTED;
		sleep((caddr_t)resource, priority);
	}
	resource->flag |= LOCKED;

	<critical section code>

	if (resource->flag & WANTED)
		wakeup((caddr_t)resource);
	resource->flag &= ~(LOCKED|WANTED);

Since the locking code is a while loop, forcing a wakeup would have no
effect.

Fortunately, that is not how things work.  If the `priority' argument
to sleep() is greater than PZERO, a signal will force an exit by a
non-local `goto' (longjmp()) out of sleep().  Long-term sleepers can
and should sleep above PZERO, arranging to catch longjmp()s and clean
up after themselves as necessary.  (This is easier in newer Sun and
SysV kernels; it seems likely that 4.4BSD's synchronisation mechanisms
will have changed as well.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris