From edf5c73201f87ebd973c4e5404a00e9fa92bed2a Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 16 Sep 2010 00:50:40 -0700 Subject: [PATCH] network - Allow asynchronous shutdown and fix a MP race in soshutdown(). * The ssb_release() call in sorflush() must be protected by socket->so_rcv.ssb_token. This call is made from the user side when soshutdown() is called. * Allow shutdowns to interrupt another thread read()ing from the same descriptor by removing the user-side interlock in the shutdown code path. --- sys/kern/uipc_socket.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index c18fc7abb7..811ba03575 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1170,6 +1170,11 @@ done: return (error); } +/* + * Shut a socket down. Note that we do not get a frontend lock as we + * want to be able to shut the socket down even if another thread is + * blocked in a read(), thus waking it up. + */ int soshutdown(struct socket *so, int how) { @@ -1177,9 +1182,9 @@ soshutdown(struct socket *so, int how) return (EINVAL); if (how != SHUT_WR) { - ssb_lock(&so->so_rcv, M_WAITOK); /* frontend lock */ + /*ssb_lock(&so->so_rcv, M_WAITOK);*/ sorflush(so); - ssb_unlock(&so->so_rcv); + /*ssb_unlock(&so->so_rcv);*/ } if (how != SHUT_RD) return (so_pru_shutdown(so)); @@ -1210,11 +1215,11 @@ sorflush(struct socket *so) ssb->ssb_mbmax = 0; atomic_clear_int(&ssb->ssb_flags, SSB_CLEAR_MASK); - lwkt_reltoken(&ssb->ssb_token); - - if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) + if ((pr->pr_flags & PR_RIGHTS) && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(asb.ssb_mb); ssb_release(&asb, so); + + lwkt_reltoken(&ssb->ssb_token); } #ifdef INET -- 2.41.0