Module Name:    src
Committed By:   kamil
Date:           Tue Oct  8 18:02:46 UTC 2019

Modified Files:
        src/sys/kern: kern_sig.c

Log Message:
Enhance reliability of ptrace(2) in a debuggee with multiple LWPs

Stop competing between threads which one emits event signal quicker and
overwriting the signal from another thread.

This fixes missed in action signals.

NetBSD truss can now report reliably all TRAP_SCE/SCX/etc events without
reports of missed ones.

his was one of the reasons why debuggee with multiple threads misbehaved
under a debugger.

This change is v.2 of the previously reverted commit for the same fix.

This version contains recovery path that stopps triggering event SIGTRAP
for a detached debugger.


To generate a diff of this commit:
cvs rdiff -u -r1.366 -r1.367 src/sys/kern/kern_sig.c

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

Modified files:

Index: src/sys/kern/kern_sig.c
diff -u src/sys/kern/kern_sig.c:1.366 src/sys/kern/kern_sig.c:1.367
--- src/sys/kern/kern_sig.c:1.366	Thu Oct  3 22:48:44 2019
+++ src/sys/kern/kern_sig.c	Tue Oct  8 18:02:46 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.366 2019/10/03 22:48:44 kamil Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.367 2019/10/08 18:02:46 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.366 2019/10/03 22:48:44 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.367 2019/10/08 18:02:46 kamil Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -913,6 +913,7 @@ trapsignal(struct lwp *l, ksiginfo_t *ks
 	mutex_enter(proc_lock);
 	mutex_enter(p->p_lock);
 
+repeat:
 	/*
 	 * If we are exiting, demise now.
 	 *
@@ -926,6 +927,16 @@ trapsignal(struct lwp *l, ksiginfo_t *ks
 		/* NOTREACHED */
 	}
 
+	/*
+	 * The process is already stopping.
+	 */
+	if ((p->p_sflag & PS_STOPPING) != 0) {
+		sigswitch(0, p->p_xsig, false);
+		mutex_enter(proc_lock);
+		mutex_enter(p->p_lock);
+		goto repeat; /* XXX */
+	}
+
 	mask = &l->l_sigmask;
 	ps = p->p_sigacts;
 	action = SIGACTION_PS(ps, signo).sa_handler;
@@ -1589,11 +1600,12 @@ eventswitch(int code, int pe_report_even
 	KASSERT((code == TRAP_CHLD) || (code == TRAP_LWP) ||
 	        (code == TRAP_EXEC));
 
+repeat:
 	/*
 	 * If we are exiting, demise now.
 	 *
 	 * This avoids notifying tracer and deadlocking.
-	*/
+	 */
 	if (__predict_false(ISSET(p->p_sflag, PS_WEXIT))) {
 		mutex_exit(p->p_lock);
 		mutex_exit(proc_lock);
@@ -1603,6 +1615,17 @@ eventswitch(int code, int pe_report_even
 	}
 
 	/*
+	 * If we are no longer traced, abandon this event signal.
+	 *
+	 * This avoids killing a process after detaching the debugger.
+	 */
+	if (__predict_false(!ISSET(p->p_slflag, PSL_TRACED))) {
+		mutex_exit(p->p_lock);
+		mutex_exit(proc_lock);
+		return;
+	}
+
+	/*
 	 * If there's a pending SIGKILL process it immediately.
 	 */
 	if (p->p_xsig == SIGKILL ||
@@ -1612,6 +1635,16 @@ eventswitch(int code, int pe_report_even
 		return;
 	}
 
+	/*
+	 * The process is already stopping.
+	 */
+	if ((p->p_sflag & PS_STOPPING) != 0) {
+		sigswitch(0, p->p_xsig, false);
+		mutex_enter(proc_lock);
+		mutex_enter(p->p_lock);
+		goto repeat; /* XXX */
+	}
+
 	KSI_INIT_TRAP(&ksi);
 	ksi.ksi_lid = l->l_lid;
 	ksi.ksi_signo = signo;
@@ -2448,6 +2481,7 @@ proc_stoptrace(int trapno, int sysnum, c
 
 	mutex_enter(p->p_lock);
 
+repeat:
 	/*
 	 * If we are exiting, demise now.
 	 *
@@ -2469,6 +2503,25 @@ proc_stoptrace(int trapno, int sysnum, c
 		return;
 	}
 
+	/*
+	 * If we are no longer traced, abandon this event signal.
+	 *
+	 * This avoids killing a process after detaching the debugger.
+	 */
+	if (__predict_false(!ISSET(p->p_slflag, PSL_TRACED))) {
+		mutex_exit(p->p_lock);
+		return;
+	}
+
+	/*
+	 * The process is already stopping.
+	 */
+	if ((p->p_sflag & PS_STOPPING) != 0) {
+		sigswitch(0, p->p_xsig, true);
+		mutex_enter(p->p_lock);
+		goto repeat; /* XXX */
+	}
+
 	/* Needed for ktrace */
 	ps = p->p_sigacts;
 	action = SIGACTION_PS(ps, signo).sa_handler;

Reply via email to