Module Name:    src
Committed By:   pooka
Date:           Thu Jan  6 06:57:14 UTC 2011

Modified Files:
        src/lib/librumpclient: rumpclient.c
        src/lib/librumpuser: rumpuser_sp.c sp_common.c

Log Message:
Make rumpclient syscalls safe to call from signal handlers.


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/lib/librumpclient/rumpclient.c
cvs rdiff -u -r1.30 -r1.31 src/lib/librumpuser/rumpuser_sp.c
cvs rdiff -u -r1.18 -r1.19 src/lib/librumpuser/sp_common.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/librumpclient/rumpclient.c
diff -u src/lib/librumpclient/rumpclient.c:1.11 src/lib/librumpclient/rumpclient.c:1.12
--- src/lib/librumpclient/rumpclient.c:1.11	Wed Jan  5 17:14:50 2011
+++ src/lib/librumpclient/rumpclient.c	Thu Jan  6 06:57:14 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpclient.c,v 1.11 2011/01/05 17:14:50 pooka Exp $	*/
+/*      $NetBSD: rumpclient.c,v 1.12 2011/01/06 06:57:14 pooka Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -60,12 +60,95 @@
 	.spc_fd = -1,
 };
 
+/*
+ * This version of waitresp is optimized for single-threaded clients
+ * and is required by signal-safe clientside rump syscalls.
+ */
+
+static void
+releasercvlock(struct spclient *spc)
+{
+
+	pthread_mutex_lock(&spc->spc_mtx);
+	if (spc->spc_istatus == SPCSTATUS_WANTED)
+		kickall(spc);
+	spc->spc_istatus = SPCSTATUS_FREE;
+}
+
+static sigset_t fullset;
+static int
+waitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask)
+{
+	struct pollfd pfd;
+	int rv = 0;
+
+	sendunlockl(spc);
+
+	rw->rw_error = 0;
+	while (rw->rw_data == NULL && rw->rw_error == 0
+	    && spc->spc_state != SPCSTATE_DYING){
+		/* are we free to receive? */
+		if (spc->spc_istatus == SPCSTATUS_FREE) {
+			spc->spc_istatus = SPCSTATUS_BUSY;
+			pthread_mutex_unlock(&spc->spc_mtx);
+
+			pfd.fd = spc->spc_fd;
+			pfd.events = POLLIN;
+
+			switch (readframe(spc)) {
+			case 0:
+				releasercvlock(spc);
+				pthread_mutex_unlock(&spc->spc_mtx);
+				pollts(&pfd, 1, NULL, mask);
+				pthread_mutex_lock(&spc->spc_mtx);
+				continue;
+			case -1:
+				releasercvlock(spc);
+				rv = errno;
+				spc->spc_state = SPCSTATE_DYING;
+				continue;
+			default:
+				break;
+			}
+
+			switch (spc->spc_hdr.rsp_class) {
+				case RUMPSP_RESP:
+				case RUMPSP_ERROR:
+					kickwaiter(spc);
+					break;
+				case RUMPSP_REQ:
+					handlereq(spc);
+					break;
+				default:
+					/* panic */
+					break;
+			}
+
+			releasercvlock(spc);
+		} else {
+			spc->spc_istatus = SPCSTATUS_WANTED;
+			pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
+		}
+	}
+	TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
+	pthread_mutex_unlock(&spc->spc_mtx);
+	pthread_cond_destroy(&rw->rw_cv);
+
+	if (rv)
+		return rv;
+	if (spc->spc_state == SPCSTATE_DYING)
+		return ENOTCONN;
+	return rw->rw_error;
+}
+
+
 static int
 syscall_req(struct spclient *spc, int sysnum,
 	const void *data, size_t dlen, void **resp)
 {
 	struct rsp_hdr rhdr;
 	struct respwait rw;
+	sigset_t omask;
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr) + dlen;
@@ -73,17 +156,21 @@
 	rhdr.rsp_type = RUMPSP_SYSCALL;
 	rhdr.rsp_sysnum = sysnum;
 
+	pthread_sigmask(SIG_SETMASK, &fullset, &omask);
 	do {
+
 		putwait(spc, &rw, &rhdr);
 		rv = dosend(spc, &rhdr, sizeof(rhdr));
 		rv = dosend(spc, data, dlen);
 		if (rv) {
 			unputwait(spc, &rw);
+			pthread_sigmask(SIG_SETMASK, &omask, NULL);
 			return rv;
 		}
 
-		rv = waitresp(spc, &rw);
+		rv = waitresp(spc, &rw, &omask);
 	} while (rv == EAGAIN);
+	pthread_sigmask(SIG_SETMASK, &omask, NULL);
 
 	*resp = rw.rw_data;
 	return rv;
@@ -95,6 +182,7 @@
 	struct handshake_fork rf;
 	struct rsp_hdr rhdr;
 	struct respwait rw;
+	sigset_t omask;
 	int rv;
 
 	/* performs server handshake */
@@ -106,6 +194,7 @@
 	else
 		rhdr.rsp_handshake = HANDSHAKE_GUEST;
 
+	pthread_sigmask(SIG_SETMASK, &fullset, &omask);
 	putwait(spc, &rw, &rhdr);
 	rv = dosend(spc, &rhdr, sizeof(rhdr));
 	if (auth) {
@@ -115,10 +204,12 @@
 	}
 	if (rv != 0 || cancel) {
 		unputwait(spc, &rw);
+		pthread_sigmask(SIG_SETMASK, &omask, NULL);
 		return rv;
 	}
 
-	rv = waitresp(spc, &rw);
+	rv = waitresp(spc, &rw, &omask);
+	pthread_sigmask(SIG_SETMASK, &omask, NULL);
 	if (rv)
 		return rv;
 
@@ -133,6 +224,7 @@
 {
 	struct rsp_hdr rhdr;
 	struct respwait rw;
+	sigset_t omask;
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr);
@@ -140,15 +232,17 @@
 	rhdr.rsp_type = RUMPSP_PREFORK;
 	rhdr.rsp_error = 0;
 
-
+	pthread_sigmask(SIG_SETMASK, &fullset, &omask);
 	putwait(spc, &rw, &rhdr);
 	rv = dosend(spc, &rhdr, sizeof(rhdr));
 	if (rv != 0) {
 		unputwait(spc, &rw);
+		pthread_sigmask(SIG_SETMASK, &omask, NULL);
 		return rv;
 	}
 
-	rv = waitresp(spc, &rw);
+	rv = waitresp(spc, &rw, &omask);
+	pthread_sigmask(SIG_SETMASK, &omask, NULL);
 	*resp = rw.rw_data;
 	return rv;
 }
@@ -263,7 +357,7 @@
 		send_anonmmap_resp(spc, spc->spc_hdr.rsp_reqno, mapaddr);
 		break;
 	default:
-		printf("PANIC: INVALID TYPE\n");
+		printf("PANIC: INVALID TYPE %d\n", reqtype);
 		abort();
 		break;
 	}
@@ -351,6 +445,7 @@
 		return -1;
 	}
 
+	sigfillset(&fullset);
 	return 0;
 }
 

Index: src/lib/librumpuser/rumpuser_sp.c
diff -u src/lib/librumpuser/rumpuser_sp.c:1.30 src/lib/librumpuser/rumpuser_sp.c:1.31
--- src/lib/librumpuser/rumpuser_sp.c:1.30	Wed Jan  5 22:57:01 2011
+++ src/lib/librumpuser/rumpuser_sp.c	Thu Jan  6 06:57:14 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpuser_sp.c,v 1.30 2011/01/05 22:57:01 pooka Exp $	*/
+/*      $NetBSD: rumpuser_sp.c,v 1.31 2011/01/06 06:57:14 pooka Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: rumpuser_sp.c,v 1.30 2011/01/05 22:57:01 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_sp.c,v 1.31 2011/01/06 06:57:14 pooka Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -98,6 +98,82 @@
 static pthread_mutex_t pfmtx;
 
 /*
+ * This version is for the server.  It's optimized for multiple threads
+ * and is *NOT* reentrant wrt to signals
+ */
+static int
+waitresp(struct spclient *spc, struct respwait *rw)
+{
+	struct pollfd pfd;
+	int rv = 0;
+
+	sendunlockl(spc);
+
+	rw->rw_error = 0;
+	while (rw->rw_data == NULL && rw->rw_error == 0
+	    && spc->spc_state != SPCSTATE_DYING){
+		/* are we free to receive? */
+		if (spc->spc_istatus == SPCSTATUS_FREE) {
+			int gotresp;
+
+			spc->spc_istatus = SPCSTATUS_BUSY;
+			pthread_mutex_unlock(&spc->spc_mtx);
+
+			pfd.fd = spc->spc_fd;
+			pfd.events = POLLIN;
+
+			for (gotresp = 0; !gotresp; ) {
+				switch (readframe(spc)) {
+				case 0:
+					poll(&pfd, 1, INFTIM);
+					continue;
+				case -1:
+					rv = errno;
+					spc->spc_state = SPCSTATE_DYING;
+					goto cleanup;
+				default:
+					break;
+				}
+
+				switch (spc->spc_hdr.rsp_class) {
+				case RUMPSP_RESP:
+				case RUMPSP_ERROR:
+					kickwaiter(spc);
+					gotresp = spc->spc_hdr.rsp_reqno ==
+					    rw->rw_reqno;
+					break;
+				case RUMPSP_REQ:
+					handlereq(spc);
+					break;
+				default:
+					/* panic */
+					break;
+				}
+			}
+ cleanup:
+			pthread_mutex_lock(&spc->spc_mtx);
+			if (spc->spc_istatus == SPCSTATUS_WANTED)
+				kickall(spc);
+			spc->spc_istatus = SPCSTATUS_FREE;
+		} else {
+			spc->spc_istatus = SPCSTATUS_WANTED;
+			pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
+		}
+	}
+
+	TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
+	pthread_mutex_unlock(&spc->spc_mtx);
+
+	pthread_cond_destroy(&rw->rw_cv);
+
+	if (rv)
+		return rv;
+	if (spc->spc_state == SPCSTATE_DYING)
+		return ENOTCONN;
+	return rw->rw_error;
+}
+
+/*
  * Manual wrappers, since librump does not have access to the
  * user namespace wrapped interfaces.
  */

Index: src/lib/librumpuser/sp_common.c
diff -u src/lib/librumpuser/sp_common.c:1.18 src/lib/librumpuser/sp_common.c:1.19
--- src/lib/librumpuser/sp_common.c:1.18	Wed Jan  5 17:14:50 2011
+++ src/lib/librumpuser/sp_common.c	Thu Jan  6 06:57:14 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: sp_common.c,v 1.18 2011/01/05 17:14:50 pooka Exp $	*/
+/*      $NetBSD: sp_common.c,v 1.19 2011/01/06 06:57:14 pooka Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -347,78 +347,6 @@
 }
 
 static int
-waitresp(struct spclient *spc, struct respwait *rw)
-{
-	struct pollfd pfd;
-	int rv = 0;
-
-	sendunlockl(spc);
-
-	rw->rw_error = 0;
-	while (rw->rw_data == NULL && rw->rw_error == 0
-	    && spc->spc_state != SPCSTATE_DYING){
-		/* are we free to receive? */
-		if (spc->spc_istatus == SPCSTATUS_FREE) {
-			int gotresp;
-
-			spc->spc_istatus = SPCSTATUS_BUSY;
-			pthread_mutex_unlock(&spc->spc_mtx);
-
-			pfd.fd = spc->spc_fd;
-			pfd.events = POLLIN;
-
-			for (gotresp = 0; !gotresp; ) {
-				switch (readframe(spc)) {
-				case 0:
-					poll(&pfd, 1, INFTIM);
-					continue;
-				case -1:
-					rv = errno;
-					spc->spc_state = SPCSTATE_DYING;
-					goto cleanup;
-				default:
-					break;
-				}
-
-				switch (spc->spc_hdr.rsp_class) {
-				case RUMPSP_RESP:
-				case RUMPSP_ERROR:
-					kickwaiter(spc);
-					gotresp = spc->spc_hdr.rsp_reqno ==
-					    rw->rw_reqno;
-					break;
-				case RUMPSP_REQ:
-					handlereq(spc);
-					break;
-				default:
-					/* panic */
-					break;
-				}
-			}
- cleanup:
-			pthread_mutex_lock(&spc->spc_mtx);
-			if (spc->spc_istatus == SPCSTATUS_WANTED)
-				kickall(spc);
-			spc->spc_istatus = SPCSTATUS_FREE;
-		} else {
-			spc->spc_istatus = SPCSTATUS_WANTED;
-			pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
-		}
-	}
-
-	TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
-	pthread_mutex_unlock(&spc->spc_mtx);
-
-	pthread_cond_destroy(&rw->rw_cv);
-
-	if (rv)
-		return rv;
-	if (spc->spc_state == SPCSTATE_DYING)
-		return ENOTCONN;
-	return rw->rw_error;
-}
-
-static int
 readframe(struct spclient *spc)
 {
 	int fd = spc->spc_fd;

Reply via email to