diff options
author | Rick Macklem <rmacklem@FreeBSD.org> | 2009-06-04 14:13:06 +0000 |
---|---|---|
committer | Rick Macklem <rmacklem@FreeBSD.org> | 2009-06-04 14:13:06 +0000 |
commit | a4fa5e6dd9017ed6d7550099bb0a0a12801d487e (patch) | |
tree | cc0d48c0c71f2161d578f4ba91009671a5e3a128 /sys/rpc/svc_vc.c | |
parent | c421791e77500b5a4883bbee54d6750ab828bed4 (diff) | |
download | src-a4fa5e6dd9017ed6d7550099bb0a0a12801d487e.tar.gz src-a4fa5e6dd9017ed6d7550099bb0a0a12801d487e.zip |
Fix two races in the server side krpc w.r.t upcalls:
Add a flag so that soupcall_clear() is only called once to cancel
an upcall.
Move the test for xprt_registered in the upcall down to after the
mtx_lock() of the pool mutex, to catch the case where it is
unregistered while the upcall is waiting for the mutex.
Also, move the mtx_destroy() of the pool mutex to after SVC_RELEASE(),
so that it isn't destroyed before the upcalls are disabled.
Reviewed by: dfr, jhb
Tested by: pho
Approved by: kib (mentor)
Notes
Notes:
svn path=/head/; revision=193436
Diffstat (limited to 'sys/rpc/svc_vc.c')
-rw-r--r-- | sys/rpc/svc_vc.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index be366de87b7f..7249270c5bdd 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -160,6 +160,7 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, solisten(so, SOMAXCONN, curthread); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -234,6 +235,7 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) xprt_register(xprt); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -352,7 +354,10 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); sx_xunlock(&xprt->xp_lock); @@ -397,7 +402,10 @@ static void svc_vc_destroy_common(SVCXPRT *xprt) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); sx_destroy(&xprt->xp_lock); @@ -632,7 +640,10 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); cd->strm_stat = XPRT_DIED; |