Module Name:    src
Committed By:   martin
Date:           Tue Oct 15 19:08:46 UTC 2019

Modified Files:
        src/sys/kern [netbsd-9]: kern_sig.c

Log Message:
Pull up following revision(s) (requested by kamil in ticket #324):

        sys/kern/kern_sig.c: revision 1.367

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.364.2.2 -r1.364.2.3 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.364.2.2 src/sys/kern/kern_sig.c:1.364.2.3
--- src/sys/kern/kern_sig.c:1.364.2.2	Tue Oct 15 19:01:06 2019
+++ src/sys/kern/kern_sig.c	Tue Oct 15 19:08:46 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.364.2.2 2019/10/15 19:01:06 martin Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.364.2.3 2019/10/15 19:08:46 martin 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.364.2.2 2019/10/15 19:01:06 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.364.2.3 2019/10/15 19:08:46 martin 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