kern/79138: close while sending on connected UNIX-domain
socket can return ENOTCONN, should return EPIPE or 0
James Juran
James.Juran at baesystems.com
Tue Mar 22 09:50:39 PST 2005
Sorry about the line wrapping on the description. Here's a properly
wrapped version of the description field:
The test program shown below, when run on a uniproc system compiled with
PREEMPTION and FULL_PREEMPTION, shows that calling send() for more than
2048 bytes on a UNIX-domain connection-oriented socket can return ENOTCONN,
even when the socket is connected. This happens when the other side of
the connection does a partial recv() and then closes the connection with
data still in the send buffer. The send() should return either EPIPE, if
the close happens before the send completes, or 0 if the send completes
before the close takes effect.
What happens is that sosend() breaks the send into 2048-byte chunks and
calls uipc_send() for each one. uipc_send() wakes up a process waiting
in recv(). In the GENERIC kernel on uniproc, this wakeup doesn't actually
take effect until sosend() tries to get the SOCKBUF_LOCK at the bottom of
the main loop. It then checks SBS_CANTSENDMORE on the next loop iteration,
and returns EPIPE as it should. However, with option FULL_PREEMPTION, the
process doing the recv() gets run right away, and performs its close before
the second call to uipc_send(). uipc_send() then fails the check for
SS_ISCONNECTED and returns ENOTCONN.
Even though this failure requires FULL_PREEMPTION to reproduce on uniproc,
I would think that on SMP there would be a chance of failure even on a
standard kernel.
More information about the freebsd-bugs
mailing list