From: Denys V. <dvl...@re...> - 2008-12-17 18:13:32
|
Hi, Testing my SIGTRAP-handling patch further, I looked into this peculiar thing where strace does something (not really clear what) when process tries to mask or SIG_IGN SIGTRAP. (Noticed and quick-fixed a typo where we weren't printing SIG_IGN correctly, in cvs now). To see this, grep for TCB_SIGTRAPPED. For example: int sys_signal(tcp) struct tcb *tcp; { if (entering(tcp)) { printsignal(tcp->u_arg[0]); tprintf(", "); switch (tcp->u_arg[1]) { case (long) SIG_ERR: tprintf("SIG_ERR"); break; case (long) SIG_DFL: tprintf("SIG_DFL"); break; case (long) SIG_IGN: #ifndef USE_PROCFS if (tcp->u_arg[0] == SIGTRAP) { fprintf(stderr, "HERE\n"); // tcp->flags |= TCB_SIGTRAPPED; // kill(tcp->pid, SIGSTOP); } #endif /* !USE_PROCFS */ tprintf("SIG_IGN"); break; default: #ifndef USE_PROCFS if (tcp->u_arg[0] == SIGTRAP) { fprintf(stderr, "HERE 1\n"); // tcp->flags |= TCB_SIGTRAPPED; // kill(tcp->pid, SIGSTOP); } #endif /* !USE_PROCFS */ tprintf("%#lx", tcp->u_arg[1]); } I verified that these code paths are reached when my test program sets SIGTRAP to something which is not SIG_DFL, and that we pass thru corresponding handling when we see this SIGSTOP: if (WSTOPSIG(status) == SIGSTOP && (tcp->flags & TCB_SIGTRAPPED)) { fprintf(stderr, "HERE 2\n"); /* * Trapped attempt to block SIGTRAP * Hope we are back in control now. */ tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) { perror("trace: ptrace(PTRACE_SYSCALL, ...)"); cleanup(); return -1; } continue; } However, when I commented out setting of TCB_SIGTRAPPED and kill() as shown above, strace still works. (At least my patched one, at least on F9 kernel). Does anybody know/remember why this TCB_SIGTRAPPED trick is even needed? I want to document it in comments. The strange thing, this handling is present in sys_signal and sys_sigaction (that is, on "older" routines) but not in sys_rt_sigaction! So, sys_rt_sigaction (which is what used by any modern libc) will not make strace to handle blocking of SIGTRAP specially, and we all know it seems to work just fine, no breakage. ?! My test program: #define _GNU_SOURCE #include <signal.h> #include <stdio.h> #include <unistd.h> #include <sys/syscall.h> void trap() { write(2, "TRAP\n", 5); } int main() { // just using signal() would use sys_rt_sigaction! syscall(SYS_signal, (long) SIGTRAP, (long) &trap); // or SIG_IGN printf("%d\n", getpid()); fflush(NULL); sleep(9); write(2, "EXIT\n", 5); return 0; } I had to build it with 32-bit compiler (i486-linux-uclibc-gcc) since x86_64 arch does not have SYS_signal, and sys_rt_sigaction would not excercise these code paths in strace. -- vda |