4.2BSD non-blocking sockets and selects

Brian Thomson thomson at utcsrgv.UUCP
Tue Jan 17 10:34:36 AEST 1984


It's been almost a month since I suggested allowing partial writes
to non-blocking stream sockets.  Faithful readers will remember that
such a change cures a tendency of rlogind(8C) and telnetd(8C) to
devour cpu cycles.  I also asked for comments.  Let's delve into the
ol' newsbag and see what lively discussion ensued:

>From: ka at hou3c.UUCP (Kenneth Almquist)
>Message-ID: <148 at hou3c.UUCP>
>Date: Thu, 22-Dec-83 10:17:31 EST
>Organization: Bell Labs, Holmdel, NJ
>
>It looks like Brian's proposed change would make writes to pipes non-atomic.
>					Kenneth Almquist

Well ... yes and no.  It only affects writes to pipes whose write ends have
been marked non-blocking.  Such writes are indeed rendered non-atomic, but
I don't know how important that is.  But note that ordinary, synchronous pipes
may not be 'atomic' in 4.2 depending on your definition of that term.
Two reasonable definitions are:
 1) No other process attempting to write on the socket (pipe) can
    intersperse data.
 2) The written data will be buffered in the kernel at one go, so the
    write can complete without a corresponding read being performed.
Previous Unix systems guaranteed 1) if the write was less than PIPSIZ, and
guaranteed 2) if the pipe was not full and the write was less than PIPSIZ.

On synchronous stream sockets, the distributed 4.2 guarantees property 1)
for writes of any size, but 2) only happens if there is adequate space
in the pipe's send queue.
My modifications do not affect this behaviour.

On non-blocking stream sockets, distributed 4.2 REQUIRES that all writes
to pipes be less than PIPSIZ (the limit also exists for non-pipes but may
differ in value).  It guarantees either that both 1) and 2) will be satisfied
or the write will return with an EMSGSIZE error.
My modifications remove the size requirement for all stream sockets
by permitting partial writes, but sacrifice atomicity by both definitions.
I also make select() and send() agree on whether a socket can be written,
which was the original intent of the change.

If it becomes necessary, atomicity can be restored by employing the
(currently unused) so->so_snd.sb_lowat field.  Set it to PIPSIZ-1 for pipes,
and leave it 0 for everyone else, then change the definition of
sowriteable() to include the term
	sbspace(&so->so_snd) > so->so_snd.sb_lowat
instead of
	sbspace(&so->so_snd) > 0
But I don't want to start using a field that the Berkeley people may
have designs for, and besides, I'm not so sure that anything is broken
enough to need fixing.  Just how dependent are people on atomic pipes,
and what kind of atomicity do they need?

Hmmm ... I seem to have reached the bottom of the ol' newsbag.
Not such a lively discussion after all.  Maybe nobody cares.  Sniff.
-- 
			Brian Thomson,	    CSRG Univ. of Toronto
			{linus,ihnp4,uw-beaver,floyd,utzoo}!utcsrgv!thomson



More information about the Comp.bugs.4bsd.ucb-fixes mailing list