2007-08-02 Jan Kratochvil <jan.kratochvil@redhat.com>
* strace.c (detach): Moved the resume notification code to ... (resume_from_tcp): ... a new function here. (handle_group_exit): No longer detach also the thread group leader. (trace): Fixed panic on exit of the TCB_GROUP_EXITING leader itself.
This commit is contained in:
parent
7b5dd1e146
commit
1bfd310325
147
strace.c
147
strace.c
@ -1337,6 +1337,71 @@ struct tcb *tcp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
resume_from_tcp (struct tcb *tcp)
|
||||
{
|
||||
int error = 0;
|
||||
int resumed = 0;
|
||||
|
||||
/* XXX This won't always be quite right (but it never was).
|
||||
A waiter with argument 0 or < -1 is waiting for any pid in
|
||||
a particular pgrp, which this child might or might not be
|
||||
in. The waiter will only wake up if it's argument is -1
|
||||
or if it's waiting for tcp->pid's pgrp. It makes a
|
||||
difference to wake up a waiter when there might be more
|
||||
traced children, because it could get a false ECHILD
|
||||
error. OTOH, if this was the last child in the pgrp, then
|
||||
it ought to wake up and get ECHILD. We would have to
|
||||
search the system for all pid's in the pgrp to be sure.
|
||||
|
||||
&& (t->waitpid == -1 ||
|
||||
(t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
|
||||
|| (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
|
||||
*/
|
||||
|
||||
if (tcp->parent &&
|
||||
(tcp->parent->flags & TCB_SUSPENDED) &&
|
||||
(tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
|
||||
error = resume(tcp->parent);
|
||||
++resumed;
|
||||
}
|
||||
#ifdef TCB_CLONE_THREAD
|
||||
if (tcp->parent && tcp->parent->nclone_waiting > 0) {
|
||||
/* Some other threads of our parent are waiting too. */
|
||||
unsigned int i;
|
||||
|
||||
/* Resume all the threads that were waiting for this PID. */
|
||||
for (i = 0; i < tcbtabsize; i++) {
|
||||
struct tcb *t = tcbtab[i];
|
||||
if (t->parent == tcp->parent && t != tcp
|
||||
&& ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
== (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
&& t->waitpid == tcp->pid) {
|
||||
error |= resume (t);
|
||||
++resumed;
|
||||
}
|
||||
}
|
||||
if (resumed == 0)
|
||||
/* Noone was waiting for this PID in particular,
|
||||
so now we might need to resume some wildcarders. */
|
||||
for (i = 0; i < tcbtabsize; i++) {
|
||||
struct tcb *t = tcbtab[i];
|
||||
if (t->parent == tcp->parent && t != tcp
|
||||
&& ((t->flags
|
||||
& (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
== (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
&& t->waitpid <= 0
|
||||
) {
|
||||
error |= resume (t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !USE_PROCFS */
|
||||
|
||||
/* detach traced process; continue with sig
|
||||
@ -1351,7 +1416,7 @@ int sig;
|
||||
{
|
||||
int error = 0;
|
||||
#ifdef LINUX
|
||||
int status, resumed, catch_sigstop;
|
||||
int status, catch_sigstop;
|
||||
struct tcb *zombie = NULL;
|
||||
|
||||
/* If the group leader is lingering only because of this other
|
||||
@ -1465,66 +1530,9 @@ int sig;
|
||||
#endif /* SUNOS4 */
|
||||
|
||||
#ifndef USE_PROCFS
|
||||
resumed = 0;
|
||||
|
||||
/* XXX This won't always be quite right (but it never was).
|
||||
A waiter with argument 0 or < -1 is waiting for any pid in
|
||||
a particular pgrp, which this child might or might not be
|
||||
in. The waiter will only wake up if it's argument is -1
|
||||
or if it's waiting for tcp->pid's pgrp. It makes a
|
||||
difference to wake up a waiter when there might be more
|
||||
traced children, because it could get a false ECHILD
|
||||
error. OTOH, if this was the last child in the pgrp, then
|
||||
it ought to wake up and get ECHILD. We would have to
|
||||
search the system for all pid's in the pgrp to be sure.
|
||||
|
||||
&& (t->waitpid == -1 ||
|
||||
(t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
|
||||
|| (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
|
||||
*/
|
||||
|
||||
if (tcp->parent &&
|
||||
(tcp->parent->flags & TCB_SUSPENDED) &&
|
||||
(tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
|
||||
error = resume(tcp->parent);
|
||||
++resumed;
|
||||
}
|
||||
#ifdef TCB_CLONE_THREAD
|
||||
if (tcp->parent && tcp->parent->nclone_waiting > 0) {
|
||||
/* Some other threads of our parent are waiting too. */
|
||||
unsigned int i;
|
||||
|
||||
/* Resume all the threads that were waiting for this PID. */
|
||||
for (i = 0; i < tcbtabsize; i++) {
|
||||
struct tcb *t = tcbtab[i];
|
||||
if (t->parent == tcp->parent && t != tcp
|
||||
&& ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
== (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
&& t->waitpid == tcp->pid) {
|
||||
error |= resume (t);
|
||||
++resumed;
|
||||
}
|
||||
}
|
||||
if (resumed == 0)
|
||||
/* Noone was waiting for this PID in particular,
|
||||
so now we might need to resume some wildcarders. */
|
||||
for (i = 0; i < tcbtabsize; i++) {
|
||||
struct tcb *t = tcbtab[i];
|
||||
if (t->parent == tcp->parent && t != tcp
|
||||
&& ((t->flags
|
||||
& (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
== (TCB_CLONE_THREAD|TCB_SUSPENDED))
|
||||
&& t->waitpid <= 0
|
||||
) {
|
||||
error |= resume (t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
error |= resume_from_tcp (tcp);
|
||||
#endif
|
||||
|
||||
#endif /* !USE_PROCFS */
|
||||
|
||||
if (!qflag)
|
||||
fprintf(stderr, "Process %u detached\n", tcp->pid);
|
||||
|
||||
@ -2109,6 +2117,9 @@ handle_group_exit(struct tcb *tcp, int sig)
|
||||
"PANIC: handle_group_exit: %d leader %d\n",
|
||||
tcp->pid, leader ? leader->pid : -1);
|
||||
/* TCP no longer exists therefore you must not detach () it. */
|
||||
#ifndef USE_PROCFS
|
||||
resume_from_tcp (tcp);
|
||||
#endif
|
||||
droptcb(tcp); /* Already died. */
|
||||
}
|
||||
else {
|
||||
@ -2116,21 +2127,8 @@ handle_group_exit(struct tcb *tcp, int sig)
|
||||
tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
|
||||
if (tcp->flags & TCB_ATTACHED) {
|
||||
detach(tcp, sig);
|
||||
if (leader != NULL && leader != tcp) {
|
||||
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. */
|
||||
if (debug)
|
||||
fprintf(stderr,
|
||||
" [%d exit %d detaches %d]\n",
|
||||
tcp->pid, sig, leader->pid);
|
||||
detach(leader, sig);
|
||||
}
|
||||
else
|
||||
leader->flags |= TCB_GROUP_EXITING;
|
||||
}
|
||||
if (leader != NULL && leader != tcp)
|
||||
leader->flags |= TCB_GROUP_EXITING;
|
||||
}
|
||||
else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
|
||||
perror("strace: ptrace(PTRACE_CONT, ...)");
|
||||
@ -2318,6 +2316,7 @@ Process %d attached (waiting for parent)\n",
|
||||
#ifdef TCB_GROUP_EXITING
|
||||
&& !(tcp->parent && (tcp->parent->flags &
|
||||
TCB_GROUP_EXITING))
|
||||
&& !(tcp->flags & TCB_GROUP_EXITING)
|
||||
#endif
|
||||
)
|
||||
fprintf(stderr,
|
||||
|
Loading…
x
Reference in New Issue
Block a user