Prevent the hiwatermark for the unix domain socket from becoming

effectively negative. Often seen as upstream fastcgi connection timeouts
in nginx when using sendfile over unix domain sockets for communication.

Sendfile(2) may send more bytes then currently allowed by the
hiwatermark of the socket, e.g. because the so_snd sockbuf lock is
dropped after sbspace() call in the kern_sendfile() loop. In this case,
recalculated hiwatermark will overflow. Since lowatermark is renewed
as half of the hiwatermark by sendfile code, and both are unsigned,
the send buffer never reaches the free space requested by lowatermark,
causing indefinite wait in sendfile.

Reviewed by:	rwatson
Approved by:	re (bz)
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2011-08-20 16:12:29 +00:00
parent fbaee0f1f5
commit aab4f50170

View File

@ -816,7 +816,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct unpcb *unp, *unp2;
struct socket *so2;
u_int mbcnt_delta, sbcc;
u_long newhiwat;
u_int newhiwat;
int error = 0;
unp = sotounpcb(so);
@ -974,7 +974,10 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
sorwakeup_locked(so2);
SOCKBUF_LOCK(&so->so_snd);
newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
if ((int)so->so_snd.sb_hiwat >= (int)(sbcc - unp2->unp_cc))
newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
else
newhiwat = 0;
(void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
newhiwat, RLIM_INFINITY);
so->so_snd.sb_mbmax -= mbcnt_delta;