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;