Module Name:    src
Committed By:   kamil
Date:           Tue Jun  4 11:54:04 UTC 2019

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

Log Message:
Stop trying to inform debugger about events from an exiting child

Do not emit signals to parent for if a process is demising:

 - fork/vfork/similar
 - lwp created/exited
 - exec
 - syscall entry/exit

With these changes Go applications can be traced without a clash under
a debugger, at least without deadlocking always. The culprit reason was
an attempt to inform a debugger in the middle of exit1() call about
a dying LWP. Go applications perform exit(2) without collecting threads
first. Verified with GDB and picotrace-based utilities like sigtracer.

PR kern/53120
PR port-arm/51677
PR bin/54060
PR bin/49662
PR kern/52548


To generate a diff of this commit:
cvs rdiff -u -r1.201 -r1.202 src/sys/kern/kern_lwp.c
cvs rdiff -u -r1.358 -r1.359 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_lwp.c
diff -u src/sys/kern/kern_lwp.c:1.201 src/sys/kern/kern_lwp.c:1.202
--- src/sys/kern/kern_lwp.c:1.201	Fri May 17 03:34:26 2019
+++ src/sys/kern/kern_lwp.c	Tue Jun  4 11:54:03 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lwp.c,v 1.201 2019/05/17 03:34:26 ozaki-r Exp $	*/
+/*	$NetBSD: kern_lwp.c,v 1.202 2019/06/04 11:54:03 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -211,7 +211,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.201 2019/05/17 03:34:26 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.202 2019/06/04 11:54:03 kamil Exp $");
 
 #include "opt_ddb.h"
 #include "opt_lockdebug.h"
@@ -1084,9 +1084,17 @@ lwp_exit(struct lwp *l)
 	if ((p->p_slflag & (PSL_TRACED|PSL_TRACELWP_EXIT)) ==
 	    (PSL_TRACED|PSL_TRACELWP_EXIT)) {
 		mutex_enter(p->p_lock);
-		p->p_lwp_exited = l->l_lid;
-		eventswitch(TRAP_LWP);
-		mutex_enter(proc_lock);
+		if (ISSET(p->p_sflag, PS_WEXIT)) {
+			mutex_exit(p->p_lock);
+			/*
+			 * We are exiting, bail out without informing parent
+			 * about a terminating LWP as it would deadlock.
+			 */
+		} else {
+			p->p_lwp_exited = l->l_lid;
+			eventswitch(TRAP_LWP);
+			mutex_enter(proc_lock);
+		}
 	}
 
 	LIST_REMOVE(l, l_list);

Index: src/sys/kern/kern_sig.c
diff -u src/sys/kern/kern_sig.c:1.358 src/sys/kern/kern_sig.c:1.359
--- src/sys/kern/kern_sig.c:1.358	Mon May  6 08:05:03 2019
+++ src/sys/kern/kern_sig.c	Tue Jun  4 11:54:03 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.358 2019/05/06 08:05:03 kamil Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.359 2019/06/04 11:54:03 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.358 2019/05/06 08:05:03 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.359 2019/06/04 11:54:03 kamil Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -913,6 +913,19 @@ trapsignal(struct lwp *l, ksiginfo_t *ks
 	mutex_enter(proc_lock);
 	mutex_enter(p->p_lock);
 
+	/*
+	 * 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);
+		lwp_exit(l);
+		panic("trapsignal");
+		/* NOTREACHED */
+	}
+
 	mask = &l->l_sigmask;
 	ps = p->p_sigacts;
 	action = SIGACTION_PS(ps, signo).sa_handler;
@@ -1569,6 +1582,19 @@ eventswitch(int code)
 	        (code == TRAP_EXEC));
 
 	/*
+	 * 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);
+		lwp_exit(l);
+		panic("eventswitch");
+		/* NOTREACHED */
+	}
+
+	/*
 	 * If there's a pending SIGKILL process it immediately.
 	 */
 	if (p->p_xsig == SIGKILL ||
@@ -1622,6 +1648,21 @@ sigswitch(int ppmask, int signo, bool re
 	KASSERT(p->p_nrlwps > 0);
 
 	/*
+	 * 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);
+		if (relock) {
+			mutex_exit(proc_lock);
+		}
+		lwp_exit(l);
+		panic("sigswitch");
+		/* NOTREACHED */
+	}
+
+	/*
 	 * On entry we know that the process needs to stop.  If it's
 	 * the result of a 'sideways' stop signal that has been sourced
 	 * through issignal(), then stop other LWPs in the process too.
@@ -2395,6 +2436,18 @@ proc_stoptrace(int trapno, int sysnum, c
 	mutex_enter(p->p_lock);
 
 	/*
+	 * 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);
+		lwp_exit(l);
+		panic("proc_stoptrace");
+		/* NOTREACHED */
+	}
+
+	/*
 	 * If there's a pending SIGKILL process it immediately.
 	 */
 	if (p->p_xsig == SIGKILL ||

Reply via email to