From: Roland McGrath Date: Thu, 5 Jul 2007 18:43:16 +0000 (+0000) Subject: 2007-07-05 Jan Kratochvil X-Git-Tag: v4.5.18~219 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0a463880341945df08b6dc79134dc78cc38dc283;p=strace 2007-07-05 Jan Kratochvil * strace.c (detach): New prototype. Extended the function comment. [LINUX] (detach): Call droptcb() instead of the wrongly parametrized detach() call. (handle_group_exit): Call droptcb() instead of the wrongly parametrized detach() call. Always call detach() only once from the group leader. Comment the leader killing known bug tested by `test/leaderkill.c'. Code advisory: Roland McGrath Fixes RH#240961. --- diff --git a/strace.c b/strace.c index 4e860403..ce982dc6 100644 --- a/strace.c +++ b/strace.c @@ -98,6 +98,7 @@ unsigned int nprocs, tcbtabsize; char *progname; extern char **environ; +static int detach P((struct tcb *tcp, int sig)); static int trace P((void)); static void cleanup P((void)); static void interrupt P((int sig)); @@ -1332,7 +1333,10 @@ struct tcb *tcp; #endif /* !USE_PROCFS */ -/* detach traced process; continue with sig */ +/* detach traced process; continue with sig + Never call DETACH twice on the same process as both unattached and + attached-unstopped processes give the same ESRCH. For unattached process we + would SIGSTOP it and wait for its SIGSTOP notification forever. */ static int detach(tcp, sig) @@ -1521,8 +1525,10 @@ int sig; droptcb(tcp); #ifdef LINUX - if (zombie != NULL) - error = detach(zombie) || error; + if (zombie != NULL) { + /* TCP no longer exists therefore you must not detach () it. */ + droptcb(zombie); + } #endif return error; @@ -2096,14 +2102,16 @@ handle_group_exit(struct tcb *tcp, int sig) fprintf(stderr, "PANIC: handle_group_exit: %d leader %d\n", tcp->pid, leader ? leader->pid : -1); - detach(tcp); /* Already died. */ + /* TCP no longer exists therefore you must not detach () it. */ + droptcb(tcp); /* Already died. */ } else { /* Mark that we are taking the process down. */ tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING; if (tcp->flags & TCB_ATTACHED) { if (leader != NULL && leader != tcp) { - if (leader->flags & TCB_ATTACHED) { + if ((leader->flags & TCB_ATTACHED) && + !(leader->flags & TCB_EXITING)) { /* We need to detach the leader so that the process death will be reported to its real parent. @@ -2115,7 +2123,10 @@ handle_group_exit(struct tcb *tcp, int sig) stopped. Then the value we pass in PTRACE_DETACH just sets the death signal reported to the - real parent. */ + real parent. + FIXME: This killing gets caught by + WAITPID of the leader's parent. + Testcase: test/leaderkill.c */ ptrace(PTRACE_KILL, leader->pid, 0, 0); if (debug) fprintf(stderr,