Subject: soisdisconnected/soisconnected & EPIPE
To: None <tech-kern@netbsd.org>
From: Iain Hibbert <plunky@rya-online.net>
List: tech-kern
Date: 11/16/2005 20:01:54
Hi,
   not sure if this should be tech-net but I think here is good.

in the socket code (uipc_socket2.c) there are two calls, soisconnected()
and soisdisconnected() which do the obvious thing. Except that, from a
userland point of view I'm not sure if something is amiss..  if a program
wants to do:

	s = socket(..)

	connect(s, ...)
	send(s, ....)

	connect(s, ...)
	send(s, ...)

	close(s)

which is permitted on some sockets according to the manpage, then how this
translates into the protocol usrreq is:

 user         usrreq         action

socket      PRU_ATTACH

connect     PRU_CONNECT     soisconnected()
send        PRU_SEND        ..

connect     PRU_DISCONNECT  soisdisconnected()
            PRU_CONNECT     soisconnected()

send        PRU_SEND        ..

close       PRU_DISCONNECT  soisdisconnected()
            PRU_DETACH

which seems normal until the second send happens, and we get EPIPE
(broken pipe) back (actually before it gets to usrreq)

I investigated and found that this is because soisdisconnected() sets
SS_CANTSENDMORE & SS_CANTRCVMORE which would be fine but soisconnected()
does not clear them and thats what causes the broken pipe when you try to
send afterwards

how to get around this:

	a) dont do it, use sendto() instead..

	b) for PRU_DISCONNECT, dont actually call soisdisconnected(), just
		so->so_state &= ~SS_ISCONNECTED

	c) for PRU_CONNECT make sure the bits are cleared

	d) change soisconnected() to clear those bits.

	e) other

if anybody has an opinion then let it out..
iain