On Wed, 17 Sep 2008, Brad wrote:
> Although the paths look Ok this diff does not apply. Does Alpine have 
> the same issue with munging diffs as Pine does?

Yeah: for the record, the fix for alpine is to add "quell-flowed-text" to 
the "feature-list" assign in .pinerc (i.e., "Do not send flowed text" in 
the visual config editor).

Here it is again (this time for sure!)

Philip


Index: sys/kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.73
diff -u -r1.73 kern_exit.c
--- sys/kern/kern_exit.c	11 May 2008 23:54:40 -0000	1.73
+++ sys/kern/kern_exit.c	17 Sep 2008 03:45:20 -0000
@@ -97,7 +97,9 @@
 int
 sys_threxit(struct proc *p, void *v, register_t *retval)
 {
-	struct sys_threxit_args *uap = v;
+	struct sys_threxit_args /* {
+		syscallarg(int) rval;
+	} */ *uap = v;
 
 	exit1(p, W_EXITCODE(SCARG(uap, rval), 0), EXIT_THREAD);
 
@@ -137,7 +139,7 @@
 		 */
 		atomic_setbits_int(&p->p_p->ps_mainproc->p_flag, P_IGNEXITRV);
 		p->p_p->ps_mainproc->p_xstat = rv;
-		psignal(p->p_p->ps_mainproc, SIGKILL);
+		ptsignal(p->p_p->ps_mainproc, SIGKILL, SPROPAGATED);
 		tsleep(p->p_p, PUSER, "thrdying", 0);
 	} else if (p == p->p_p->ps_mainproc) {
 		atomic_setbits_int(&p->p_flag, P_WEXIT);
@@ -147,7 +149,7 @@
 				nq = TAILQ_NEXT(q, p_thr_link);
 				atomic_setbits_int(&q->p_flag, P_IGNEXITRV);
 				q->p_xstat = rv;
-				psignal(q, SIGKILL);
+				ptsignal(q, SIGKILL, SPROPAGATED);
 			}
 		}
 		wakeup(p->p_p);
Index: sys/kern/kern_prot.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_prot.c,v
retrieving revision 1.31
diff -u -r1.31 kern_prot.c
--- sys/kern/kern_prot.c	22 May 2008 21:27:40 -0000	1.31
+++ sys/kern/kern_prot.c	17 Sep 2008 03:45:20 -0000
@@ -77,7 +77,8 @@
 	register_t *retval;
 {
 
-	*retval = p->p_pid;
+	*retval = p->p_pid
+		+ (p->p_p->ps_mainproc == p ? THREAD_PID_OFFSET : 0);
 	return (0);
 }
 #endif
Index: sys/kern/kern_sig.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.99
diff -u -r1.99 kern_sig.c
--- sys/kern/kern_sig.c	10 Jun 2008 20:41:52 -0000	1.99
+++ sys/kern/kern_sig.c	17 Sep 2008 03:45:21 -0000
@@ -577,13 +577,30 @@
 	if ((u_int)SCARG(uap, signum) >= NSIG)
 		return (EINVAL);
 	if (SCARG(uap, pid) > 0) {
-		/* kill single process */
+		enum signal_type type = SPROCESS;
+
+#ifdef RTHREADS
+		if (SCARG(uap, pid) > THREAD_PID_OFFSET) {
+			if ((p = pfind(SCARG(uap, pid)
+					- THREAD_PID_OFFSET)) == NULL)
+				return (ESRCH);
+			if (p->p_p->ps_mainproc != p)
+				return (ESRCH);
+			type = STHREAD;
+		} else
+#endif
 		if ((p = pfind(SCARG(uap, pid))) == NULL)
 			return (ESRCH);
+#ifdef RTHREADS
+		else if (p->p_flag & P_THREAD)
+			type = STHREAD;
+#endif
+
+		/* kill single process */
 		if (!cansignal(cp, pc, p, SCARG(uap, signum)))
 			return (EPERM);
 		if (SCARG(uap, signum))
-			psignal(p, SCARG(uap, signum));
+			ptsignal(p, SCARG(uap, signum), type);
 		return (0);
 	}
 	switch (SCARG(uap, pid)) {
@@ -614,7 +631,7 @@
 		 * broadcast
 		 */
 		LIST_FOREACH(p, &allproc, p_list) {
-			if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || 
+			if (p->p_pid <= 1 || p->p_flag & (P_SYSTEM|P_THREAD) ||
 			    p == cp || !cansignal(cp, pc, p, signum))
 				continue;
 			nfound++;
@@ -633,7 +650,7 @@
 				return (ESRCH);
 		}
 		LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
-			if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
+			if (p->p_pid <= 1 || p->p_flag & (P_SYSTEM|P_THREAD) ||
 			    !cansignal(cp, pc, p, signum))
 				continue;
 			nfound++;
@@ -747,7 +764,7 @@
 		ps->ps_code = code;	/* XXX for core dump/debugger */
 		ps->ps_type = type;
 		ps->ps_sigval = sigval;
-		psignal(p, signum);
+		ptsignal(p, signum, STHREAD);
 	}
 }
 
@@ -767,6 +784,18 @@
 void
 psignal(struct proc *p, int signum)
 {
+	ptsignal(p, signum, SPROCESS);
+}
+
+/*
+**  type = SPROCESS	process signal, can be diverted (sigwait())
+**	XXX if blocked in all threads, mark as pending in struct process
+**  type = STHREAD	thread signal, but should be propagated if unhandled
+**  type = SPROPAGATED	propagated to this thread, so don't propagate again
+*/
+void
+ptsignal(struct proc *p, int signum, enum signal_type type)
+{
 	int s, prop;
 	sig_t action;
 	int mask;
@@ -784,21 +813,23 @@
 	if (p->p_flag & P_WEXIT)
 		return;
 
+	mask = sigmask(signum);
+
 #ifdef RTHREADS
-	TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
-		if (q == p)
-			continue;
-		if (q->p_sigdivert & (1 << signum)) {
-			q->p_sigdivert = 0;
-			psignal(q, signum);
-			return;
+	if (type == SPROCESS) {
+		TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
+			if (q == p)
+				continue;
+			if (q->p_sigdivert & mask) {
+				ptsignal(q, signum, STHREAD);
+				return;
+			}
 		}
 	}
 #endif
 
 	KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
 
-	mask = sigmask(signum);
 	prop = sigprop[signum];
 
 	/*
@@ -814,9 +845,17 @@
 		 * and if it is set to SIG_IGN,
 		 * action will be SIG_DFL here.)
 		 */
+#ifdef RTHREADS
+		if (p->p_sigdivert & mask) {
+			p->p_sigwait = signum;
+			atomic_clearbits_int(&p->p_sigdivert, ~0);
+			action = SIG_CATCH;
+			wakeup(&p->p_sigdivert);
+		} else
+#endif
 		if (p->p_sigignore & mask)
 			return;
-		if (p->p_sigmask & mask)
+		else if (p->p_sigmask & mask)
 			action = SIG_HOLD;
 		else if (p->p_sigcatch & mask)
 			action = SIG_CATCH;
@@ -838,29 +877,28 @@
 	}
 
 	if (prop & SA_CONT) {
-#ifdef RTHREADS
-		TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
-			if (q != p)
-				psignal(q, signum);
-		 }
-#endif
 		atomic_clearbits_int(&p->p_siglist, stopsigmask);
 	}
 
 	if (prop & SA_STOP) {
-#ifdef RTHREADS
-		
-		TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
-			if (q != p)
-				psignal(q, signum);
-		 }
-#endif
 		atomic_clearbits_int(&p->p_siglist, contsigmask);
 		atomic_clearbits_int(&p->p_flag, P_CONTINUED);
 	}
 
 	atomic_setbits_int(&p->p_siglist, mask);
 
+#ifdef RTHREADS
+	/*
+	 * XXX delay processing of SA_STOP signals unless action == SIG_DFL?
+	 */
+	if (prop & (SA_CONT | SA_STOP) && type != SPROPAGATED) {
+		TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
+			if (q != p)
+				ptsignal(q, signum, SPROPAGATED);
+		}
+	}
+#endif
+
 	/*
 	 * Defer further processing for signals which are held,
 	 * except that stopped processes must be continued by SIGCONT.
@@ -1451,7 +1489,7 @@
 sys_nosys(struct proc *p, void *v, register_t *retval)
 {
 
-	psignal(p, SIGSYS);
+	ptsignal(p, SIGSYS, STHREAD);
 	return (ENOSYS);
 }
 
@@ -1459,10 +1497,43 @@
 int
 sys_thrsigdivert(struct proc *p, void *v, register_t *retval)
 {
-	struct sys_thrsigdivert_args *uap = v;
+	struct sys_thrsigdivert_args /* {
+		syscallarg(sigset_t) sigmask;
+	} */ *uap = v;
+	sigset_t mask;
+	sigset_t *m;
+	int error;
+
+	m = NULL;
+	mask = SCARG(uap, sigmask) &~ sigcantmask;
+
+	/* pending signal for this thread? */
+	if (p->p_siglist & mask)
+		m = &p->p_siglist;
+	else if (p->p_p->ps_mainproc->p_siglist & mask)
+		m = &p->p_p->ps_mainproc->p_siglist;
+	if (m != NULL) {
+		int sig = ffs((long)(*m & mask));
+		atomic_clearbits_int(m, sigmask(sig));
+		*retval = sig;
+		return (0);
+	}
 
-	p->p_sigdivert = SCARG(uap, sigmask);
+	p->p_sigwait = 0;
+	atomic_setbits_int(&p->p_sigdivert, mask);
+	error = tsleep(&p->p_sigdivert, PPAUSE|PCATCH, "sigwait", 0);
+	if (p->p_sigdivert) {
+		/* interrupted */
+		KASSERT(error != 0);
+		atomic_clearbits_int(&p->p_sigdivert, ~0);
+		if (error == ERESTART)
+			error = EINTR;
+		return (error);
 
+	}
+	KASSERT(error == 0);
+	KASSERT(p->p_sigwait != 0);
+	*retval = p->p_sigwait;
 	return (0);
 }
 #endif
Index: sys/kern/sys_generic.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.58
diff -u -r1.58 sys_generic.c
--- sys/kern/sys_generic.c	7 Sep 2007 15:00:20 -0000	1.58
+++ sys/kern/sys_generic.c	17 Sep 2008 03:45:21 -0000
@@ -337,7 +337,7 @@
 		    error == EINTR || error == EWOULDBLOCK))
 			error = 0;
 		if (error == EPIPE)
-			psignal(p, SIGPIPE);
+			ptsignal(p, SIGPIPE, STHREAD);
 	}
 	cnt -= auio.uio_resid;
 
@@ -448,7 +448,7 @@
 		    error == EINTR || error == EWOULDBLOCK))
 			error = 0;
 		if (error == EPIPE)
-			psignal(p, SIGPIPE);
+			ptsignal(p, SIGPIPE, STHREAD);
 	}
 	cnt -= auio.uio_resid;
 
Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.68
diff -u -r1.68 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c	23 May 2008 15:51:12 -0000	1.68
+++ sys/kern/uipc_syscalls.c	17 Sep 2008 03:45:21 -0000
@@ -523,7 +523,7 @@
 		    error == EINTR || error == EWOULDBLOCK))
 			error = 0;
 		if (error == EPIPE)
-			psignal(p, SIGPIPE);
+			ptsignal(p, SIGPIPE, STHREAD);
 	}
 	if (error == 0) {
 		*retsize = len - auio.uio_resid;
Index: sys/sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.103
diff -u -r1.103 proc.h
--- sys/sys/proc.h	5 May 2008 15:37:41 -0000	1.103
+++ sys/sys/proc.h	17 Sep 2008 03:45:22 -0000
@@ -185,6 +185,7 @@
 	int	p_dupfd;	 /* Sideways return value from filedescopen. XXX */
 
 	long 	p_thrslpid;	/* for thrsleep syscall */
+	int	p_sigwait;	/* signal handled by sigwait() */
 
 
 	/* scheduling */
@@ -349,6 +350,7 @@
  */
 #define	PID_MAX		32766
 #define	NO_PID		(PID_MAX+1)
+#define THREAD_PID_OFFSET	1000000
 
 #define SESS_LEADER(p)	((p)->p_session->s_leader == (p))
 #define	SESSHOLD(s)	((s)->s_count++)
Index: sys/sys/signalvar.h
===================================================================
RCS file: /cvs/src/sys/sys/signalvar.h,v
retrieving revision 1.16
diff -u -r1.16 signalvar.h
--- sys/sys/signalvar.h	6 Feb 2007 18:42:37 -0000	1.16
+++ sys/sys/signalvar.h	17 Sep 2008 03:45:22 -0000
@@ -160,6 +160,8 @@
 void	pgsignal(struct pgrp *pgrp, int sig, int checkctty);
 void	postsig(int sig);
 void	psignal(struct proc *p, int sig);
+enum signal_type { SPROCESS, STHREAD, SPROPAGATED };
+void	ptsignal(struct proc *p, int sig, enum signal_type type);
 void	siginit(struct proc *p);
 void	trapsignal(struct proc *p, int sig, u_long code, int type,
 	    union sigval val);
Index: lib/librthread/rthread.c
===================================================================
RCS file: /cvs/src/lib/librthread/rthread.c,v
retrieving revision 1.38
diff -u -r1.38 rthread.c
--- lib/librthread/rthread.c	14 Aug 2008 05:57:06 -0000	1.38
+++ lib/librthread/rthread.c	17 Sep 2008 03:45:22 -0000
@@ -345,6 +345,12 @@
 }
 
 int
+raise(int sig)
+{
+	return (kill(getthrid(), sig));
+}
+
+int
 pthread_kill(pthread_t thread, int sig)
 {
 	return (kill(thread->tid, sig));
Index: lib/librthread/rthread.h
===================================================================
RCS file: /cvs/src/lib/librthread/rthread.h,v
retrieving revision 1.18
diff -u -r1.18 rthread.h
--- lib/librthread/rthread.h	5 Jun 2008 21:06:11 -0000	1.18
+++ lib/librthread/rthread.h	17 Sep 2008 03:45:23 -0000
@@ -119,7 +119,6 @@
 	struct pthread_attr attr;
 	struct sched_param sched_param;
 	struct rthread_storage *local_storage;
-	int sigpend;
 	struct rthread_cleanup_fn *cleanup_fns;
 };
 #define	THREAD_DONE		0x001
Index: lib/librthread/rthread_sig.c
===================================================================
RCS file: /cvs/src/lib/librthread/rthread_sig.c,v
retrieving revision 1.5
diff -u -r1.5 rthread_sig.c
--- lib/librthread/rthread_sig.c	24 Apr 2008 11:44:26 -0000	1.5
+++ lib/librthread/rthread_sig.c	17 Sep 2008 03:45:23 -0000
@@ -42,45 +42,14 @@
 	return (sigprocmask(how, set, oset) ? errno : 0);
 }
 
-/* 
- * implementation of sigwait:
- * 1.  we install a handler for each masked signal.
- * 2.  we inform the kernel we are interested in this signal set.
- * 3.  sleep.  the handler will wake us up.
- *
- * this is atomic because the kernel will only divert one signal
- * to a thread until it asks for more.
- */
-static void
-sigwait_handler(int sig)
-{
-	pthread_t self = pthread_self();
-	self->sigpend = sig;
-	thrwakeup(&self->sigpend, 0);
-}
-
-typedef void (*sigfn)(int);
-
 int
 sigwait(const sigset_t *set, int *sig)
 {
-	int i;
-	sigset_t mask = *set;
-	pthread_t self = pthread_self();
-	sigfn oldhandlers[NSIG];
-
-	for (i = 0; i < NSIG; i++) {
-		if (mask & (1 << i))
-			oldhandlers[i] = signal(i, sigwait_handler);
-	}
-
-	thrsigdivert(set);
-	thrsleep(&self->sigpend, 0, NULL);
+	int ret;
 
-	for (i = 0; i < NSIG; i++) {
-		if (mask & (1 << i))
-			signal(i, oldhandlers[i]);
-	}
-	*sig = self->sigpend;
-	return (0);
+	ret = thrsigdivert(set);
+	if (ret == -1)
+		return errno;
+	*sig = ret;
+	return 0;
 }

