diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2015-07-28 14:20:11 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2015-07-28 14:20:11 +0000 |
commit | fe6d8727a6e4c5332e5f59fe7a73717ff906a7d0 (patch) | |
tree | 926a92d2862f27a2125e890f33dae12f18913129 | |
parent | cc7a006e08daa77cf81b424da9a08ed491a0728f (diff) |
For unix domain sequenced packet socket pairs the ruby regression
tests reported an EMSGSIZE error although the sent message was not
too large. The way backpressure was implemented for unix domain
sockets confused the check in sosend().
Unix domain sockets append data only to the recv buffer. To report
the amount of content to the sender, the high watermark of the send
buffer was reduced. This happend for SOCK_STREAM and SOCK_SEQPACKET.
Sosend checks wether atomic chunks could ever fit into the send
buffer which is limited by the high watermark. This happens for
SOCK_DGRAM and SOCK_SEQPACKET. For SOCK_SEQPACKET the combination
of these mechanisms resulted in an EMSGSIZE error when the buffer
got filled. This also happened when space could be created by
reading from the other end in contradiction to the semantics of
EMSGSIZE.
Do not emulate a send buffer that has no space. It is better to
fill the buffer with fake data than to reduce its size. Thus the
high watermark always contains the real value. When disconnecting,
reset the counters. Otherwise the socket layer would try to flush
non existing data in the send buffer.
Tested by jeremy@ with a C program and the ruby tests.
OK markus@ jeremy@
-rw-r--r-- | sys/kern/uipc_usrreq.c | 34 |
1 files changed, 11 insertions, 23 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 6eed2562825..dcb64b05b1e 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.82 2015/07/18 15:00:01 guenther Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.83 2015/07/28 14:20:10 bluhm Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -162,10 +162,8 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, * Adjust backpressure on sender * and wakeup any waiting to write. */ - snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt; - unp->unp_mbcnt = rcv->sb_mbcnt; - snd->sb_hiwat += unp->unp_cc - rcv->sb_cc; - unp->unp_cc = rcv->sb_cc; + snd->sb_mbcnt = rcv->sb_mbcnt; + snd->sb_cc = rcv->sb_cc; sowwakeup(so2); #undef snd #undef rcv @@ -228,8 +226,8 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, } so2 = unp->unp_conn->unp_socket; /* - * Send to paired receive port, and then reduce - * send buffer hiwater marks to maintain backpressure. + * Send to paired receive port, and then raise + * send buffer counts to maintain backpressure. * Wake up readers. */ if (control) { @@ -239,11 +237,8 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, sbappendrecord(rcv, m); else sbappend(rcv, m); - snd->sb_mbmax -= - rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt; - unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt; - snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc; - unp->unp_conn->unp_cc = rcv->sb_cc; + snd->sb_mbcnt = rcv->sb_mbcnt; + snd->sb_cc = rcv->sb_cc; sorwakeup(so2); m = NULL; #undef snd @@ -266,17 +261,6 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct stat *sb = (struct stat *)m; sb->st_blksize = so->so_snd.sb_hiwat; - switch (so->so_type) { - case SOCK_STREAM: - case SOCK_SEQPACKET: - if (unp->unp_conn != NULL) { - so2 = unp->unp_conn->unp_socket; - sb->st_blksize += so2->so_rcv.sb_cc; - } - break; - default: - break; - } sb->st_dev = NODEV; if (unp->unp_ino == 0) unp->unp_ino = unp_ino++; @@ -589,8 +573,12 @@ unp_disconnect(struct unpcb *unp) case SOCK_STREAM: case SOCK_SEQPACKET: + unp->unp_socket->so_snd.sb_mbcnt = 0; + unp->unp_socket->so_snd.sb_cc = 0; soisdisconnected(unp->unp_socket); unp2->unp_conn = NULL; + unp2->unp_socket->so_snd.sb_mbcnt = 0; + unp2->unp_socket->so_snd.sb_cc = 0; soisdisconnected(unp2->unp_socket); break; } |