aboutsummaryrefslogtreecommitdiff
path: root/sys/rpc/svc_vc.c
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2009-06-04 14:13:06 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2009-06-04 14:13:06 +0000
commita4fa5e6dd9017ed6d7550099bb0a0a12801d487e (patch)
treecc0d48c0c71f2161d578f4ba91009671a5e3a128 /sys/rpc/svc_vc.c
parentc421791e77500b5a4883bbee54d6750ab828bed4 (diff)
downloadsrc-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.c17
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;