I've been investigating the race in ptrace(2) ATF tests: dbregs_* for x86 (i386 and amd64). Examples: NetBSD/amd64 http://releng.netbsd.org/b5reports/amd64/2018/2018.03.06.11.21.31/test.html#lib_libc_sys_t_ptrace_wait6_dbregs_dr3_trap_variable_readwrite_write_2bytes NetBSD/i386 http://releng.netbsd.org/b5reports/i386/2017/2017.12.06.17.54.58/test.html#lib_libc_sys_t_ptrace_wait3_dbregs_dr2_trap_variable_readwrite_read_2bytes I still don't know what is the root cause for the race and I'm open for suggestions. Observations: 1. This bug is reproducible only for the scenario with debug register trap according to the tests of mine. 2. It's reproducible on slower x86 hardware or in softemu (qemu). I have not been able to reproduce a single failure on post-Core2Duo CPU. 3. Adding or changing the scenario slightly of tests (like to PT_STEP or changing SIGSTOP to other signal) makes the test disappear at all. 4. Adding almost any debug code anywhere makes this test either disappear or make reproducible much less frequently (sometimes once a day). 5. I've detected that the bug is caused by the fact that _lwp_kill(2) (called via raise(2)) [under a debugger] can trigger two calls of wait(2) to return for the same signal. A few days ago, I've prepared this document: http://netbsd.org/~kamil/kernel/sigstop.txt 6. According to my tests in lwp_userret(): 1549 /* 1550 * It is safe to do this read unlocked on a MP system.. 1551 */ 1552 while ((l->l_flag & LW_USERRET) != 0) { 1553 /* 1554 * Process pending signals first, unless the process 1555 * is dumping core or exiting, where we will instead 1556 * enter the LW_WSUSPEND case below. 1557 */ 1558 if ((l->l_flag & (LW_PENDSIG | LW_WCORE | LW_WEXIT)) == 1559 LW_PENDSIG) { 1560 mutex_enter(p->p_lock); 1561 while ((sig = issignal(l)) != 0) 1562 postsig(sig); 1563 mutex_exit(p->p_lock); 1564 } 1565 -- src/sys/kern/kern_lwp.c We always enter the while() loop and call issignal(). Sometimes we extract a signal and call postsig(). Usually for the call, we see no misbehavior. 7. I've checked that PT_CONTINUE branch where p_stat != SSTOP is never taken, at least for this race. We always call: 828 /* Finally, deliver the requested signal (or none). */ 829 if (t->p_stat == SSTOP) { 830 /* 831 * Unstop the process. If it needs to take a 832 * signal, make all efforts to ensure that at 833 * an LWP runs to see it. 834 */ 835 t->p_xsig = signo; 836 if (resume_all) 837 proc_unstop(t); 838 else 839 lwp_unstop(lt); 840 return 0; 841 } -- src/sys/kern/sys_ptrace_common.c 8. We checked that we call sigpost() twice for a single _lwp_kill(2) call: A. handle_syscall() -> syscall() -> sv_invoke() -> sys__lwp_kill() -> kpsignal2() -> sigpost() B. lwp_userret() -> issignal() -> sigswitch() -> proc_stop() -> sigpost() 9. Adding two consequential wait(2) calls, one after (checking for error condition for another with WNOHANG) - makes the bug disappear completely. I'm looking for hints to speedup the research.
Attachment:
signature.asc
Description: OpenPGP digital signature