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 ||