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;