summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2012-04-13 16:37:50 +0000
committerkettenis <kettenis@openbsd.org>2012-04-13 16:37:50 +0000
commit4ec195400d023537d947ee6557938900b7cc7161 (patch)
treeae5a44c0389aa411ffbe8060c039ba000dad12a8 /sys/kern/kern_sig.c
parentDon't try to mmap a 0-length file. (diff)
downloadwireguard-openbsd-4ec195400d023537d947ee6557938900b7cc7161.tar.xz
wireguard-openbsd-4ec195400d023537d947ee6557938900b7cc7161.zip
First stab at making ptrace(2) usable for debugging multi-threaded programs.
It implements a full-stop model where all threads are stopped before handing over control to the debugger. Events are reported as before through wait(2); you will have to call ptrace(PT_GET_PROCESS_STATE, ...) to find out which thread hit the event. Since this changes the size of struct ptrace_state, you will have to recompile gdb. ok guenther@
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 991744db1d3..c1cb5857ce0 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.140 2012/04/12 10:11:41 mikeb Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.141 2012/04/13 16:37:51 kettenis Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -1072,12 +1072,20 @@ issignal(struct proc *p)
*/
p->p_xstat = signum;
+ KERNEL_LOCK();
+ single_thread_set(p, SINGLE_SUSPEND, 0);
+ KERNEL_UNLOCK();
+
if (dolock)
SCHED_LOCK(s);
proc_stop(p, 1);
if (dolock)
SCHED_UNLOCK(s);
+ KERNEL_LOCK();
+ single_thread_clear(p, 0);
+ KERNEL_UNLOCK();
+
/*
* If we are no longer being traced, or the parent
* didn't give us a signal, look for more signals.
@@ -1766,7 +1774,7 @@ single_thread_set(struct proc *p, enum single_thread_mode mode, int deep)
TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) {
int s;
- if (q == p)
+ if (q == p || ISSET(q->p_flag, P_WEXIT))
continue;
SCHED_LOCK(s);
atomic_setbits_int(&q->p_flag, P_SUSPSINGLE);
@@ -1812,7 +1820,7 @@ single_thread_set(struct proc *p, enum single_thread_mode mode, int deep)
}
void
-single_thread_clear(struct proc *p)
+single_thread_clear(struct proc *p, int flag)
{
struct process *pr = p->p_p;
struct proc *q;
@@ -1834,7 +1842,7 @@ single_thread_clear(struct proc *p)
* it back into some sleep queue
*/
SCHED_LOCK(s);
- if (q->p_stat == SSTOP && (q->p_flag & P_SUSPSIG) == 0) {
+ if (q->p_stat == SSTOP && (q->p_flag & flag) == 0) {
if (q->p_wchan == 0)
setrunnable(q);
else