No more malloc or lock inside signal handlers.
diff --git a/src/lib9/9proc.h b/src/lib9/9proc.h
index 713b955..663d65b 100644
--- a/src/lib9/9proc.h
+++ b/src/lib9/9proc.h
@@ -2,15 +2,12 @@
 {
 	NPRIV = 16,
 	RENDHASH = 33,
-	PIDHASH = 33,
 };
 
 typedef struct Uproc Uproc;
 struct Uproc
 {
-	Uproc *next;
 	int pid;
-	int pipe[2];
 	int state;
 	void *priv[NPRIV];
 	ulong rendval;
@@ -19,5 +16,5 @@
 	p9jmp_buf notejb;
 };
 
-extern Uproc *_p9uproc(void);
+extern Uproc *_p9uproc(int);
 extern void _p9uprocdie(void);
diff --git a/src/lib9/_p9proc.c b/src/lib9/_p9proc.c
index 6e4010c..374fb08 100644
--- a/src/lib9/_p9proc.c
+++ b/src/lib9/_p9proc.c
@@ -1,73 +1,95 @@
+/*
+ * This needs to be callable from a signal handler, so it has been
+ * written to avoid locks.  The only lock is the one used to acquire
+ * an entry in the table, and we make sure that acquiring is done
+ * when not in a handler.  Lookup and delete do not need locks.
+ * It's a scan-forward hash table.  To avoid breaking chains, 
+ * T ((void*)-1) is used as a non-breaking nil.
+ */
+
 #include <u.h>
 #include <libc.h>
 #include "9proc.h"
 
+enum { PIDHASH = 1021 };
+
+#define T ((void*)-1)
+static Uproc *alluproc[PIDHASH];
+static int allupid[PIDHASH];
 static Lock uproclock;
-static Uproc *phash[PIDHASH];
 
 Uproc*
-_p9uproc(void)
+_p9uproc(int inhandler)
 {
-	/* for now, assume getpid is fast or cached */
-	int pid;
+	int i, h, pid;
 	Uproc *up;
 
+	/* for now, assume getpid is fast or cached */
 	pid = getpid();
-again:
-if(0)print("find %d\n", pid);
-	lock(&uproclock);
-	for(up=phash[pid%PIDHASH]; up; up=up->next){
-		if(up->pid == pid){
-if(0)print("found %d\n", pid);
-			unlock(&uproclock);
+
+	/*
+	 * this part - the lookup - needs to run without locks
+	 * so that it can safely be called from within the notify handler.
+	 * notify calls _p9uproc, and fork and rfork call _p9uproc
+	 * in both parent and child, so if we're in a signal handler,
+	 * we should find something in the table.
+	 */
+	h = pid%PIDHASH;
+	for(i=0; i<PIDHASH; i++){
+		up = alluproc[h];
+		if(up == nil)
+			break;
+		if(allupid[h] == pid)
 			return up;
-		}
+		if(++h == PIDHASH)
+			h = 0;
 	}
 
+	if(inhandler)
+		sysfatal("did not find uproc in signal handler");
+
+	/* need to allocate */
+	while((up = mallocz(sizeof(Uproc), 1)) == nil)
+		sleep(1000);
+
 	up = mallocz(sizeof(Uproc), 1);
-	if(up == nil){
-if(0)print("again %d\n", pid);
-		unlock(&uproclock);
-		sleep(1000);
-		goto again;
+	lock(&uproclock);
+	h = pid%PIDHASH;
+	for(i=0; i<PIDHASH; i++){
+		if(alluproc[h]==T || alluproc[h]==nil){
+			alluproc[h] = up;
+			allupid[h] = pid;
+			return up;
+		}
+		if(++h == PIDHASH)
+			h = 0;
 	}
-
-againpipe:
-	if(pipe(up->pipe) < 0){
-if(0)print("againpipe %d\n", pid);
-		sleep(1000);
-		goto againpipe;
-	}
-
-	up->pid = pid;
-	up->next = phash[pid%PIDHASH];
-	phash[pid%PIDHASH] = up;
-if(0)print("link %d\n", pid);
 	unlock(&uproclock);
-	return up;
+
+	/* out of pids! */
+	sysfatal("too many processes in uproc table");
+	return nil;
 }
 
 void
 _p9uprocdie(void)
 {
-	Uproc **l, *up;
-	int pid;
+	Uproc *up;
+	int pid, i, h;
 
 	pid = getpid();
-if(0)print("die %d\n", pid);
-	lock(&uproclock);
-	for(l=&phash[pid%33]; *l; l=&(*l)->next){
-		if((*l)->pid == pid){
-			up = *l;
-			*l = up->next;
-if(0)print("died %d\n", pid);
-			unlock(&uproclock);
-			close(up->pipe[0]);
-			close(up->pipe[1]);
+	h = pid%PIDHASH;
+	for(i=0; i<PIDHASH; i++){
+		up = alluproc[h];
+		if(up == nil)
+			break;
+		if(up == T)
+			continue;
+		if(allupid[h] == pid){
+			up = alluproc[h];
+			alluproc[h] = T;
 			free(up);
-			return;
+			allupid[h] = 0;
 		}
 	}
-if(0)print("not started %d\n", pid);
-	unlock(&uproclock);
 }
diff --git a/src/lib9/notify.c b/src/lib9/notify.c
index 12edb0e..79a5e62 100644
--- a/src/lib9/notify.c
+++ b/src/lib9/notify.c
@@ -49,7 +49,7 @@
 	char tmp[64];
 	Uproc *up;
 
-	up = _p9uproc();
+	up = _p9uproc(1);
 	v = p9setjmp(up->notejb);
 	if(v == 0 && notifyf)
 		(*notifyf)(nil, _p9sigstr(sig, tmp));
@@ -68,6 +68,7 @@
 	int i;
 	struct sigaction sa;
 
+	_p9uproc(0);
 	memset(&sa, 0, sizeof sa);
 	if(f == 0)
 		sa.sa_handler = SIG_DFL;
@@ -90,7 +91,7 @@
 {
 	Uproc *up;
 
-	up = _p9uproc();
+	up = _p9uproc(1);
 	p9longjmp(up->notejb, v==NCONT ? 2 : 1);
 	abort();
 	return 0;
diff --git a/src/lib9/priv.c b/src/lib9/priv.c
index 651c48c..e64e919 100644
--- a/src/lib9/priv.c
+++ b/src/lib9/priv.c
@@ -26,7 +26,7 @@
 {
 	Uproc *up;
 
-	up = _p9uproc();
+	up = _p9uproc(0);
 	return &up->priv[i];
 }
 
diff --git a/src/lib9/rendez.c b/src/lib9/rendez.c
index cf23a4e..2b2c1a1 100644
--- a/src/lib9/rendez.c
+++ b/src/lib9/rendez.c
@@ -12,7 +12,7 @@
 	ulong ret;
 	Uproc *t, *self, **l;
 
-	self = _p9uproc();
+	self = _p9uproc(0);
 	lock(&rendlock);
 	l = &rendhash[tag%RENDHASH];
 	for(t=*l; t; l=&t->rendhash, t=*l){
diff --git a/src/lib9/rfork.c b/src/lib9/rfork.c
index f3a2192..21dc17e 100644
--- a/src/lib9/rfork.c
+++ b/src/lib9/rfork.c
@@ -1,5 +1,7 @@
-#define NOPLAN9DEFINES
-#include <lib9.h>
+#include <u.h>
+#include <libc.h>
+#include "9proc.h"
+#undef rfork
 
 int
 p9rfork(int flags)
@@ -14,6 +16,7 @@
 			return -1;
 		}
 		pid = fork();
+		_p9uproc(0);
 		if(pid != 0)
 			return pid;
 	}