* More waitpid issues with CLONE_DETACHED/CLONE_THREAD
@ 2004-02-01 3:25 Daniel Jacobowitz
2004-02-01 4:38 ` Linus Torvalds
0 siblings, 1 reply; 18+ messages in thread
From: Daniel Jacobowitz @ 2004-02-01 3:25 UTC (permalink / raw)
To: linux-kernel
This may be related to the python bug reported today...
I've been playing around with gdbserver support for NPTL threading all day
today. Right now it works, except that when I say "kill" in the GDB client,
gdbserver hangs. The problem is that we kill the child, and wait for it,
but wait never returns it.
write(2, "Killing inferior\n", 17) = 17
ptrace(PTRACE_CONT, 8454, 0, SIG_0) = 0
tkill(8454, SIGKILL) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
waitpid(8454, 0xbfffec04, WNOHANG) = 0
waitpid(8454, 0xbfffec04, WNOHANG|__WCLONE) = -1 ECHILD (No child processes)
nanosleep({0, 1000000}, 0) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
setup() = 0
waitpid(8454, 0xbfffec04, WNOHANG) = 0
waitpid(8454, 0xbfffec04, WNOHANG|__WCLONE) = -1 ECHILD (No child processes)
and so on (looping on waitpid). At this point, process 8454 is marked as a
zombie, and nothing can reap it. After gdbserver is killed, it reparents to
init:
Name: linux-dp
State: Z (zombie)
SleepAVG: 91%
Tgid: 8454
Pid: 8454
PPid: 1
TracerPid: 0
but init can't reap it either.
8454 was the original (i.e. non-CLONE_DETACHED) thread. Same behavior if I
use ptrace_kill.
GDB doesn't suffer from the same problem. A little time with strace and I
found out why: GDB PTRACE_KILL's the detached threads, PTRACE_KILL's the
parent thread, waitpid's the detached threads, and then waitpid's the parent
thread. No design, just different order of items on the linked list.
If I change gdbserver to do "kill thread; wait for thread; kill next thread;
wait for next thread; kill parent last; wait for parent last" then it
terminates and I don't get an unkillable zombie.
ptrace(PTRACE_KILL, 18348, 0, 0) = 0
waitpid(18348, 0xbfffec04, WNOHANG) = -1 ECHILD (No child processes)
--- SIGCHLD (Child exited) @ 0 (0) ---
waitpid(18348, [WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL], WNOHANG|__WCLONE) = 18348
ptrace(PTRACE_KILL, 18349, 0, 0) = 0
waitpid(18349, 0xbfffec04, WNOHANG) = -1 ECHILD (No child processes)
waitpid(18349, [WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL], WNOHANG|__WCLONE) = 18349
--- SIGCHLD (Child exited) @ 0 (0) ---
ptrace(PTRACE_KILL, 18350, 0, 0) = 0
waitpid(18350, 0xbfffec04, WNOHANG) = -1 ECHILD (No child processes)
waitpid(18350, [WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL], WNOHANG|__WCLONE) = 18350
ptrace(PTRACE_KILL, 18351, 0, 0) = 0
waitpid(18351, 0xbfffec04, WNOHANG) = -1 ECHILD (No child processes)
waitpid(18351, [WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL], WNOHANG|__WCLONE) = 18351
ptrace(PTRACE_KILL, 18352, 0, 0) = 0
waitpid(18352, 0xbfffec04, WNOHANG) = -1 ECHILD (No child processes)
waitpid(18352, [WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL], WNOHANG|__WCLONE) = 18352
--- SIGCHLD (Child exited) @ 0 (0) ---
ptrace(PTRACE_KILL, 18329, 0, 0) = 0
waitpid(18329, [WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL], WNOHANG) = 18329
exit_group(0) = ?
So it looks like something gets very confused if the parent is SIGKILLed
before the children. What should happen?
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 3:25 More waitpid issues with CLONE_DETACHED/CLONE_THREAD Daniel Jacobowitz
@ 2004-02-01 4:38 ` Linus Torvalds
2004-02-01 4:43 ` Daniel Jacobowitz
0 siblings, 1 reply; 18+ messages in thread
From: Linus Torvalds @ 2004-02-01 4:38 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sat, 31 Jan 2004, Daniel Jacobowitz wrote:
>
> This may be related to the python bug reported today...
Indeed.
Having a "waitpid(x, .., WNOHANG)" return 0 is a very interesting
condition. That condition basically guarantees that:
- the kernel did find the child
- but the kernel decided that the child cannot be reaped right then.
If you see the process as a Zombie in a "ps" listing, then we know that
that isn't the reason why it couldn't be reaped. Can you verify that
/proc/<pid>/status shows it as "Z (zombie)"?
In fact, if we see it as "Z (zombie)", we know even more: it means that
wait_task_zombie() was never called, because that would have started out
with changing the process state to "X (dead)".
And that in turn implies that "eligible_child()" would have returned 2.
Which is a normal occurrence: it happens when a process group leader still
has threads attached to it. At that point it may be a Zombie, but we can't
reap it yet. The threads have to go away before the thing can be reaped.
Can you verify that that process doesn't have any sub-threads? (Again,
that should be easily visible in /proc/<pid>/task/).
Another alternative is that the process is a zombie, but it is being
traced. When that happens, it shows up on the "ptrace_children" list, and
we'll see in in wait4(), but we won't be able to reap it.
Roland, Ingo - have you followed the discussion on linux-kernel? Something
strange does seem to be going on..
Linus
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 4:38 ` Linus Torvalds
@ 2004-02-01 4:43 ` Daniel Jacobowitz
2004-02-01 5:12 ` Daniel Jacobowitz
2004-02-01 5:12 ` More waitpid issues with CLONE_DETACHED/CLONE_THREAD Linus Torvalds
0 siblings, 2 replies; 18+ messages in thread
From: Daniel Jacobowitz @ 2004-02-01 4:43 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sat, Jan 31, 2004 at 08:38:43PM -0800, Linus Torvalds wrote:
>
>
> On Sat, 31 Jan 2004, Daniel Jacobowitz wrote:
> >
> > This may be related to the python bug reported today...
>
> Indeed.
>
> Having a "waitpid(x, .., WNOHANG)" return 0 is a very interesting
> condition. That condition basically guarantees that:
>
> - the kernel did find the child
> - but the kernel decided that the child cannot be reaped right then.
>
> If you see the process as a Zombie in a "ps" listing, then we know that
> that isn't the reason why it couldn't be reaped. Can you verify that
> /proc/<pid>/status shows it as "Z (zombie)"?
Yes, it is a zombie when the waitpid is executed.
> In fact, if we see it as "Z (zombie)", we know even more: it means that
> wait_task_zombie() was never called, because that would have started out
> with changing the process state to "X (dead)".
>
> And that in turn implies that "eligible_child()" would have returned 2.
>
> Which is a normal occurrence: it happens when a process group leader still
> has threads attached to it. At that point it may be a Zombie, but we can't
> reap it yet. The threads have to go away before the thing can be reaped.
>
> Can you verify that that process doesn't have any sub-threads? (Again,
> that should be easily visible in /proc/<pid>/task/).
It is quite easily visible - in fact, it's hilarious.
8454 pts/8 Z 0:00 [linux-dp] <defunct>
drow@nevyn:~% ls /proc/8454
auxv cmdline cwd@ environ exe@ fd/ maps mem mounts root@ stat
drow@nevyn:~% ls /proc/8454/task
ls: /proc/8454/task: No such file or directory
What that means I'm not entirely sure.
> Another alternative is that the process is a zombie, but it is being
> traced. When that happens, it shows up on the "ptrace_children" list, and
> we'll see in in wait4(), but we won't be able to reap it.
At this point it is being traced - this is gdbserver. But the same
process that is tracing it is calling waitpid. And the problem
persists after the tracer dies; the process above is actually from a
couple of hours ago, and its tracer was killed.
> Roland, Ingo - have you followed the discussion on linux-kernel? Something
> strange does seem to be going on..
The only two kernels I've tried were 2.6.0-test7 and 2.6.2-rc3, by the
way - same behavior in both. I'll try to write a single program
testcase for this.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 4:43 ` Daniel Jacobowitz
@ 2004-02-01 5:12 ` Daniel Jacobowitz
2004-02-01 21:41 ` Linus Torvalds
2004-02-01 5:12 ` More waitpid issues with CLONE_DETACHED/CLONE_THREAD Linus Torvalds
1 sibling, 1 reply; 18+ messages in thread
From: Daniel Jacobowitz @ 2004-02-01 5:12 UTC (permalink / raw)
To: Linus Torvalds, Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sat, Jan 31, 2004 at 11:43:31PM -0500, Daniel Jacobowitz wrote:
> The only two kernels I've tried were 2.6.0-test7 and 2.6.2-rc3, by the
> way - same behavior in both. I'll try to write a single program
> testcase for this.
Here you go. The bug turns out not to be related directly to
CLONE_DETACHED. Compile testcase with -DNOTHREAD to use fork (well,
clone, but without the fancy flags), without -DNOTHREAD to use
CLONE_DETACHED | CLONE_THREAD.
In either mode, compile with -DBUG to kill and reap the parent before
the child. I get a variety of unkillable processes, hangs, and
unkilled parents; sometimes in the -DNOTHREAD case the parent simply is
not stopped by the PTRACE_KILL (remains in S state). If you kill -9 it
from a terminal it becomes a zombie despite the fact that its parent is
in waitpid for it.
You may need to fiddle a little bit to get this to compile depending on
your distribution of choice, it assumes some constants from
<linux/ptrace.h> that require 2.6 headers... should work on any 2.6
kernel.
/* -DBUG to kill the parent before the child -> hang. */
/* -DNOTHREAD to us fork instead of clone. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <signal.h>
#include <sys/ptrace.h>
#include <sched.h>
#include <sys/wait.h>
#include <linux/ptrace.h>
int stack_one[8192], stack_two[8192];
int thread_func_two()
{
write (1, "Thread 2\n", 9);
while (1)
sleep (1);
}
int thread_func_one()
{
int ret;
char retstr[10];
write (1, "Thread 1\n", 9);
ptrace (PTRACE_TRACEME, 0, 0, 0);
write (1, "Thread 1 signalling\n", 20);
syscall (SYS_tkill, getpid (), SIGUSR1);
write (1, "Thread 1 cloning\n", 17);
ret = clone (thread_func_two, stack_two + 8192,
#ifdef NOTHREAD
SIGCHLD,
#else
CLONE_DETACHED | CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_FS,
#endif
NULL);
sprintf (retstr, "= %d\n", ret);
write (1, retstr, strlen (retstr));
write (1, "Thread 1 sleeping\n", 18);
while (1)
sleep (1);
}
int main()
{
int ret, wstat;
int child = fork(), child2 = 0;
if (child == 0)
return thread_func_one();
ptrace (PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK);
ret = waitpid (child, &wstat, __WALL);
ptrace (PTRACE_CONT, child, 0, 0);
ret = waitpid (child, &wstat, __WALL);
ptrace (PTRACE_GETEVENTMSG, child, 0, &child2);
ret = waitpid (child2, &wstat, __WALL);
ptrace (PTRACE_CONT, child, 0, 0);
ptrace (PTRACE_CONT, child2, 0, 0);
#ifndef BUG
ptrace (PTRACE_KILL, child2, 0, 0);
ret = waitpid (child2, &wstat, __WALL);
#endif
ptrace (PTRACE_KILL, child, 0, 0);
ret = waitpid (child, &wstat, __WALL);
#ifdef BUG
ptrace (PTRACE_KILL, child2, 0, 0);
ret = waitpid (child2, &wstat, __WALL);
#endif
return 0;
}
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 4:43 ` Daniel Jacobowitz
2004-02-01 5:12 ` Daniel Jacobowitz
@ 2004-02-01 5:12 ` Linus Torvalds
2004-02-01 5:14 ` Daniel Jacobowitz
1 sibling, 1 reply; 18+ messages in thread
From: Linus Torvalds @ 2004-02-01 5:12 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sat, 31 Jan 2004, Daniel Jacobowitz wrote:
> >
> > Can you verify that that process doesn't have any sub-threads? (Again,
> > that should be easily visible in /proc/<pid>/task/).
>
> It is quite easily visible - in fact, it's hilarious.
>
> 8454 pts/8 Z 0:00 [linux-dp] <defunct>
>
> drow@nevyn:~% ls /proc/8454
> auxv cmdline cwd@ environ exe@ fd/ maps mem mounts root@ stat
>
> drow@nevyn:~% ls /proc/8454/task
> ls: /proc/8454/task: No such file or directory
Oh damn. Yeah, we don't allow you to even see the threads in this case (it
checks "pid_alive(task)". We don't want you to try to confuse things by
opening files of processes that we think are dead.
For the case of trying to figure out sub-threads of a dead thread group
leader, that may actually be a bug.
Just for testing this, you might remove the check for
if (!pid_alive(task))
goto out;
in proc_pident_lookup() in fs/proc/base.c.
Ingo - comments? We really want the sysadmin to be able to find threads
that have a dead group leader, and right now that seems to be impossible.
Linus
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 5:12 ` More waitpid issues with CLONE_DETACHED/CLONE_THREAD Linus Torvalds
@ 2004-02-01 5:14 ` Daniel Jacobowitz
2004-02-01 5:42 ` Roland McGrath
0 siblings, 1 reply; 18+ messages in thread
From: Daniel Jacobowitz @ 2004-02-01 5:14 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sat, Jan 31, 2004 at 09:12:33PM -0800, Linus Torvalds wrote:
>
>
> On Sat, 31 Jan 2004, Daniel Jacobowitz wrote:
> > >
> > > Can you verify that that process doesn't have any sub-threads? (Again,
> > > that should be easily visible in /proc/<pid>/task/).
> >
> > It is quite easily visible - in fact, it's hilarious.
> >
> > 8454 pts/8 Z 0:00 [linux-dp] <defunct>
> >
> > drow@nevyn:~% ls /proc/8454
> > auxv cmdline cwd@ environ exe@ fd/ maps mem mounts root@ stat
> >
> > drow@nevyn:~% ls /proc/8454/task
> > ls: /proc/8454/task: No such file or directory
>
> Oh damn. Yeah, we don't allow you to even see the threads in this case (it
> checks "pid_alive(task)". We don't want you to try to confuse things by
> opening files of processes that we think are dead.
>
> For the case of trying to figure out sub-threads of a dead thread group
> leader, that may actually be a bug.
>
> Just for testing this, you might remove the check for
>
> if (!pid_alive(task))
> goto out;
>
> in proc_pident_lookup() in fs/proc/base.c.
>
> Ingo - comments? We really want the sysadmin to be able to find threads
> that have a dead group leader, and right now that seems to be impossible.
I thought that a new group leader would be swapped in to that TID? But
I was always confused by the mechanics of that.
Note that processes going invisible this way is, um, a bit of a
security problem.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 5:14 ` Daniel Jacobowitz
@ 2004-02-01 5:42 ` Roland McGrath
2004-02-01 5:46 ` Daniel Jacobowitz
0 siblings, 1 reply; 18+ messages in thread
From: Roland McGrath @ 2004-02-01 5:42 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Linus Torvalds, Kernel Mailing List, Ingo Molnar
> I thought that a new group leader would be swapped in to that TID? But
> I was always confused by the mechanics of that.
The group leader never changes. The zombie group leader just sticks around
until there are no other threads in the group. (The only exception here is
exec.)
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 5:42 ` Roland McGrath
@ 2004-02-01 5:46 ` Daniel Jacobowitz
0 siblings, 0 replies; 18+ messages in thread
From: Daniel Jacobowitz @ 2004-02-01 5:46 UTC (permalink / raw)
To: Roland McGrath; +Cc: Linus Torvalds, Kernel Mailing List, Ingo Molnar
On Sat, Jan 31, 2004 at 09:42:52PM -0800, Roland McGrath wrote:
> > I thought that a new group leader would be swapped in to that TID? But
> > I was always confused by the mechanics of that.
>
> The group leader never changes. The zombie group leader just sticks around
> until there are no other threads in the group. (The only exception here is
> exec.)
Ah, thanks, it was exec that I was thinking of.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 5:12 ` Daniel Jacobowitz
@ 2004-02-01 21:41 ` Linus Torvalds
2004-02-01 22:25 ` Roland McGrath
2004-02-02 0:52 ` Daniel Jacobowitz
0 siblings, 2 replies; 18+ messages in thread
From: Linus Torvalds @ 2004-02-01 21:41 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sun, 1 Feb 2004, Daniel Jacobowitz wrote:
>
> Here you go. The bug turns out not to be related directly to
> CLONE_DETACHED. Compile testcase with -DNOTHREAD to use fork (well,
> clone, but without the fancy flags), without -DNOTHREAD to use
> CLONE_DETACHED | CLONE_THREAD.
I don't think this bug has anything to do with anything else.
This program seems to show that PTRACE_KILL simply doesn't work.
What ptrace_kill() does is effectively:
- stage 1: ptrace_check_attach(): wait for child stopped
- stage 2: PTRACE_KILL does:
child->exit_code = SIGKILL;
wake_up_process(child);
and the thing is, it looks like the signal handling changes have totally
made the child ignore the "exit_code" thing, unless I'm seriously
misreading something.
Roland, you know this code better than I do. Any comments?
I suspect the PTRACE_KILL logic should also do a
spin_lock_irqsave(child->sighand->siglock, flags);
sigaddset(&child->pending->signal, SIGKILL);
set_tsk_thread_flag(child, TIF_SIGPENDING);
spin_unlock_irqrestore(child->sighand->siglock, flags);
ptrace_detach(child);
which would set the SIGKILL thing properly, but I suspect we had a good
reason not to do it that way originally.
Daniel?
Linus
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 21:41 ` Linus Torvalds
@ 2004-02-01 22:25 ` Roland McGrath
2004-02-02 0:55 ` Linus Torvalds
2004-02-02 0:52 ` Daniel Jacobowitz
1 sibling, 1 reply; 18+ messages in thread
From: Roland McGrath @ 2004-02-01 22:25 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Daniel Jacobowitz, Kernel Mailing List, Ingo Molnar
> and the thing is, it looks like the signal handling changes have totally
> made the child ignore the "exit_code" thing, unless I'm seriously
> misreading something.
The only time that exit_code has ever been consulted is in
get_signal_to_deliver after the thread has stopped to notify its ptracer
and then been resumed. That is still the case. So it's only being ignored
if the child is stopped in some other place and not there. I don't see the
scenario where that could be happening without the explicit involvement of
user-level stop signals (i.e. not the implicit stops done by ptrace).
Your changes would be equivalent to an atomic combination of
"kill(child_pid, SIGKILL); PTRACE_DETACH(pid);". That is different from
what PTRACE_KILL normally does, which leaves the dying child attached so
that it reports its death to the ptracer before the original parent.
I haven't really looked into the problem with Dan's test case yet (didn't
seem to reproduce, but I haven't tried a current and cruft-free kernel yet).
But I don't see any problem with the implementation of PTRACE_KILL.
Thanks,
Roland
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 21:41 ` Linus Torvalds
2004-02-01 22:25 ` Roland McGrath
@ 2004-02-02 0:52 ` Daniel Jacobowitz
2004-02-02 2:41 ` Davide Libenzi
1 sibling, 1 reply; 18+ messages in thread
From: Daniel Jacobowitz @ 2004-02-02 0:52 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sun, Feb 01, 2004 at 01:41:48PM -0800, Linus Torvalds wrote:
>
>
> On Sun, 1 Feb 2004, Daniel Jacobowitz wrote:
> >
> > Here you go. The bug turns out not to be related directly to
> > CLONE_DETACHED. Compile testcase with -DNOTHREAD to use fork (well,
> > clone, but without the fancy flags), without -DNOTHREAD to use
> > CLONE_DETACHED | CLONE_THREAD.
>
> I don't think this bug has anything to do with anything else.
>
> This program seems to show that PTRACE_KILL simply doesn't work.
> and the thing is, it looks like the signal handling changes have totally
> made the child ignore the "exit_code" thing, unless I'm seriously
> misreading something.
That may be (though I don't think so) but it reproduces without
PTRACE_KILL too. Try the attached, which just replaced PTRACE_KILL
with PTRACE_CONT/tkill(pid, SIGKILL). Still get zombies. I haven't
tried reproducing entirely without ptrace yet.
> Roland, you know this code better than I do. Any comments?
>
> I suspect the PTRACE_KILL logic should also do a
>
> spin_lock_irqsave(child->sighand->siglock, flags);
> sigaddset(&child->pending->signal, SIGKILL);
> set_tsk_thread_flag(child, TIF_SIGPENDING);
> spin_unlock_irqrestore(child->sighand->siglock, flags);
>
> ptrace_detach(child);
>
> which would set the SIGKILL thing properly, but I suspect we had a good
> reason not to do it that way originally.
>
> Daniel?
I doubt there was a good reason. This code hasn't changed in a hell of
a long time - it probably predates everything up there except sigaddset
:).
/* -DBUG to kill the parent before the child -> hang. */
/* -DNOTHREAD to us fork instead of clone. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <signal.h>
#include <sys/ptrace.h>
#include <sched.h>
#include <sys/wait.h>
#include <linux/ptrace.h>
int stack_one[8192], stack_two[8192];
int thread_func_two()
{
write (1, "Thread 2\n", 9);
while (1)
sleep (1);
}
int thread_func_one()
{
int ret;
char retstr[10];
write (1, "Thread 1\n", 9);
ptrace (PTRACE_TRACEME, 0, 0, 0);
write (1, "Thread 1 signalling\n", 20);
syscall (SYS_tkill, getpid (), SIGUSR1);
write (1, "Thread 1 cloning\n", 17);
ret = clone (thread_func_two, stack_two + 8192,
#ifdef NOTHREAD
SIGCHLD,
#else
CLONE_DETACHED | CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_FS,
#endif
NULL);
sprintf (retstr, "= %d\n", ret);
write (1, retstr, strlen (retstr));
write (1, "Thread 1 sleeping\n", 18);
while (1)
sleep (1);
}
int main()
{
int ret, wstat;
int child = fork(), child2 = 0;
if (child == 0)
return thread_func_one();
ptrace (PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK);
ret = waitpid (child, &wstat, __WALL);
ptrace (PTRACE_CONT, child, 0, 0);
ret = waitpid (child, &wstat, __WALL);
ptrace (PTRACE_GETEVENTMSG, child, 0, &child2);
ret = waitpid (child2, &wstat, __WALL);
ptrace (PTRACE_CONT, child, 0, 0);
ptrace (PTRACE_CONT, child2, 0, 0);
#ifndef BUG
ptrace (PTRACE_CONT, child2, 0, 0);
syscall (SYS_tkill, child2, SIGKILL);
ret = waitpid (child2, &wstat, __WALL);
#endif
ptrace (PTRACE_CONT, child, 0, 0);
syscall (SYS_tkill, child, SIGKILL);
ret = waitpid (child, &wstat, __WALL);
#ifdef BUG
ptrace (PTRACE_CONT, child2, 0, 0);
syscall (SYS_tkill, child2, SIGKILL);
ret = waitpid (child2, &wstat, __WALL);
#endif
return 0;
}
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-01 22:25 ` Roland McGrath
@ 2004-02-02 0:55 ` Linus Torvalds
2004-02-02 2:20 ` Andries Brouwer
0 siblings, 1 reply; 18+ messages in thread
From: Linus Torvalds @ 2004-02-02 0:55 UTC (permalink / raw)
To: Roland McGrath; +Cc: Daniel Jacobowitz, Kernel Mailing List, Ingo Molnar
On Sun, 1 Feb 2004, Roland McGrath wrote:
>
> I haven't really looked into the problem with Dan's test case yet (didn't
> seem to reproduce, but I haven't tried a current and cruft-free kernel yet).
> But I don't see any problem with the implementation of PTRACE_KILL.
Hmm.. For me, Dan's program (with "-DBUG -DNOTHREAD") results in a
sleeping parent, and both children are likewise just sleeping. Despite the
fact that the parent just did the PTRACE_KILL on child2.
I didn't trace it through the kernel, it just looked like PTRACE_KILL
didn't do anything.
Linus
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-02 0:55 ` Linus Torvalds
@ 2004-02-02 2:20 ` Andries Brouwer
2004-02-02 2:30 ` Linus Torvalds
0 siblings, 1 reply; 18+ messages in thread
From: Andries Brouwer @ 2004-02-02 2:20 UTC (permalink / raw)
To: Linus Torvalds
Cc: Roland McGrath, Daniel Jacobowitz, Kernel Mailing List,
Ingo Molnar
On Sun, Feb 01, 2004 at 04:55:11PM -0800, Linus Torvalds wrote:
> On Sun, 1 Feb 2004, Roland McGrath wrote:
> > I haven't really looked into the problem with Dan's test case yet (didn't
> > seem to reproduce, but I haven't tried a current and cruft-free kernel yet).
> > But I don't see any problem with the implementation of PTRACE_KILL.
>
> Hmm.. For me, Dan's program (with "-DBUG -DNOTHREAD") results in a
> sleeping parent, and both children are likewise just sleeping. Despite the
> fact that the parent just did the PTRACE_KILL on child2.
>
> I didn't trace it through the kernel, it just looked like PTRACE_KILL
> didn't do anything.
I agree with both of you.
So, I think what happens is that PTRACE_KILL immediately after the PTRACE_CONT
works because there is no schedule in between, so the effect of PTRACE_KILL
is still seen by the (grand)child.
Once the grandchild has returned it has become immune for PTRACE_KILL.
Maybe there is no bug.
Andries
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-02 2:20 ` Andries Brouwer
@ 2004-02-02 2:30 ` Linus Torvalds
0 siblings, 0 replies; 18+ messages in thread
From: Linus Torvalds @ 2004-02-02 2:30 UTC (permalink / raw)
To: Andries Brouwer
Cc: Roland McGrath, Daniel Jacobowitz, Kernel Mailing List,
Ingo Molnar
On Mon, 2 Feb 2004, Andries Brouwer wrote:
>
> So, I think what happens is that PTRACE_KILL immediately after the PTRACE_CONT
> works because there is no schedule in between, so the effect of PTRACE_KILL
> is still seen by the (grand)child.
Well, Duh! You'r eobviously right.
PTRACE_KILL is a special case, since it's supposed to work _regardless_ of
whether the process being traced is actually stopped for tracing or not.
And Roland is correct that PTRACE_KILL works fine _if_ it is stopped.
But for the case where it isn't (and Daniel's program isn't, since it did
the PTRACE_CONT), PTRACE_KILL does nothing.
> Maybe there is no bug.
No, I do believe that PTRACE_KILL is supposed to kill the child even if it
wasn't synchronized. See the special case for "ptrace_check_attach()",
which allows a PTRACE_KILL to happen even for a nonsynchronized target.
Linus
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-02 0:52 ` Daniel Jacobowitz
@ 2004-02-02 2:41 ` Davide Libenzi
2004-02-02 2:55 ` Davide Libenzi
0 siblings, 1 reply; 18+ messages in thread
From: Davide Libenzi @ 2004-02-02 2:41 UTC (permalink / raw)
To: Daniel Jacobowitz
Cc: Linus Torvalds, Kernel Mailing List, Roland McGrath, Ingo Molnar
On Sun, 1 Feb 2004, Daniel Jacobowitz wrote:
> On Sun, Feb 01, 2004 at 01:41:48PM -0800, Linus Torvalds wrote:
> >
> >
> > On Sun, 1 Feb 2004, Daniel Jacobowitz wrote:
> > >
> > > Here you go. The bug turns out not to be related directly to
> > > CLONE_DETACHED. Compile testcase with -DNOTHREAD to use fork (well,
> > > clone, but without the fancy flags), without -DNOTHREAD to use
> > > CLONE_DETACHED | CLONE_THREAD.
> >
> > I don't think this bug has anything to do with anything else.
> >
> > This program seems to show that PTRACE_KILL simply doesn't work.
>
> > and the thing is, it looks like the signal handling changes have totally
> > made the child ignore the "exit_code" thing, unless I'm seriously
> > misreading something.
>
> That may be (though I don't think so) but it reproduces without
> PTRACE_KILL too. Try the attached, which just replaced PTRACE_KILL
> with PTRACE_CONT/tkill(pid, SIGKILL). Still get zombies. I haven't
> tried reproducing entirely without ptrace yet.
Here w/out ptrace works as advertised.
- Davide
/* -DBUG to kill the parent before the child -> hang. */
/* -DNOTHREAD to us fork instead of clone. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <signal.h>
#include <sched.h>
#include <errno.h>
#include <sys/wait.h>
int stack_one[8192], stack_two[8192];
int fds1[2], fds2[2];
int thread_func_two()
{
fprintf(stdout, "Thread 2: ppid = %d\n", getppid());
while (1) {
sleep (1);
fprintf(stdout, "Thread 2: ppid = %d\n", getppid());
}
}
int thread_func_one()
{
int ret;
fprintf(stdout, "Thread 1\n");
read(fds1[0], &ret, sizeof(int));
fprintf(stdout, "Thread 1 cloning\n");
ret = clone (thread_func_two, stack_two + 8192,
#ifdef NOTHREAD
SIGCHLD,
#else
CLONE_DETACHED | CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_FS,
#endif
NULL);
fprintf(stdout, "child2 = %d\n", ret);
write(fds2[1], &ret, sizeof(int));
fprintf(stdout, "Thread 1 sleeping\n");
while (1)
sleep (1);
}
int main()
{
int ret, wstat, child, child2;
if (pipe(fds1) < 0 || pipe(fds2)) {
perror("pipe");
return 1;
}
child = fork();
if (child == 0)
return thread_func_one();
fprintf(stdout, "child = %d\n", child);
write(fds1[1], &child, sizeof(int));
read(fds2[0], &child2, sizeof(int));
fprintf(stdout, "parent got child2 = %d\n", child2);
#ifndef BUG
kill(child2, SIGKILL);
ret = waitpid (child2, &wstat, __WALL);
fprintf(stdout, "waitpid(%d) = %d (%s)\n", child2, ret, strerror(errno));
#endif
kill(child, SIGKILL);
ret = waitpid (child, &wstat, __WALL);
fprintf(stdout, "waitpid(%d) = %d (%s)\n", child, ret, strerror(errno));
#ifdef BUG
sleep(2);
kill(child2, SIGKILL);
ret = waitpid (child2, &wstat, __WALL);
fprintf(stdout, "waitpid(%d) = %d (%s)\n", child2, ret, strerror(errno));
#endif
return 0;
}
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: More waitpid issues with CLONE_DETACHED/CLONE_THREAD
2004-02-02 2:41 ` Davide Libenzi
@ 2004-02-02 2:55 ` Davide Libenzi
2004-02-04 14:22 ` fs/eventpoll : reduce sizeof(struct epitem) dada1
0 siblings, 1 reply; 18+ messages in thread
From: Davide Libenzi @ 2004-02-02 2:55 UTC (permalink / raw)
To: Davide Libenzi
Cc: Daniel Jacobowitz, Linus Torvalds, Kernel Mailing List,
Roland McGrath, Ingo Molnar
On Sun, 1 Feb 2004, Davide Libenzi wrote:
> > That may be (though I don't think so) but it reproduces without
> > PTRACE_KILL too. Try the attached, which just replaced PTRACE_KILL
> > with PTRACE_CONT/tkill(pid, SIGKILL). Still get zombies. I haven't
> > tried reproducing entirely without ptrace yet.
>
> Here w/out ptrace works as advertised.
Yes, even for something that uses tkill() :-)
- Davide
/* -DBUG to kill the parent before the child -> hang. */
/* -DNOTHREAD to us fork instead of clone. */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <signal.h>
#include <sched.h>
#include <errno.h>
#include <sys/wait.h>
int stack_one[8192], stack_two[8192];
int fds1[2], fds2[2];
int thread_func_two()
{
fprintf(stdout, "Thread 2: ppid = %d\n", getppid());
while (1) {
sleep (1);
fprintf(stdout, "Thread 2: ppid = %d\n", getppid());
}
}
int thread_func_one()
{
int ret;
fprintf(stdout, "Thread 1\n");
read(fds1[0], &ret, sizeof(int));
fprintf(stdout, "Thread 1 cloning\n");
ret = clone (thread_func_two, stack_two + 8192,
#ifdef NOTHREAD
SIGCHLD,
#else
CLONE_DETACHED | CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_FS,
#endif
NULL);
fprintf(stdout, "child2 = %d\n", ret);
write(fds2[1], &ret, sizeof(int));
fprintf(stdout, "Thread 1 sleeping\n");
while (1)
sleep (1);
}
int main()
{
int ret, wstat, child, child2;
if (pipe(fds1) < 0 || pipe(fds2)) {
perror("pipe");
return 1;
}
child = fork();
if (child == 0)
return thread_func_one();
fprintf(stdout, "child = %d\n", child);
write(fds1[1], &child, sizeof(int));
read(fds2[0], &child2, sizeof(int));
fprintf(stdout, "parent got child2 = %d\n", child2);
#ifndef BUG
syscall(SYS_tkill, child2, SIGKILL);
ret = waitpid (child2, &wstat, __WALL);
fprintf(stdout, "waitpid(%d) = %d (%s)\n", child2, ret,
ret < 0 ? strerror(errno): "Success");
#endif
syscall(SYS_tkill, child, SIGKILL);
ret = waitpid (child, &wstat, __WALL);
fprintf(stdout, "waitpid(%d) = %d (%s)\n", child, ret,
ret < 0 ? strerror(errno): "Success");
#ifdef BUG
sleep(2);
syscall(SYS_tkill, child2, SIGKILL);
ret = waitpid (child2, &wstat, __WALL);
fprintf(stdout, "waitpid(%d) = %d (%s)\n", child2, ret,
ret < 0 ? strerror(errno): "Success");
#endif
return 0;
}
^ permalink raw reply [flat|nested] 18+ messages in thread
* fs/eventpoll : reduce sizeof(struct epitem)
2004-02-02 2:55 ` Davide Libenzi
@ 2004-02-04 14:22 ` dada1
2004-02-05 4:23 ` Davide Libenzi
0 siblings, 1 reply; 18+ messages in thread
From: dada1 @ 2004-02-04 14:22 UTC (permalink / raw)
To: Davide Libenzi; +Cc: Kernel Mailing List
Hi Davide
On a x86_64 platform, I noticed that the size of (struct epitem) is 136
bytes, rounded to 192 (because of L1_CACHE alignment of 64 bytes)
If you reorder some fields of this structure, we can reduce the size to
128 bytes.
The rationale is to group nwait & fd integer (32bits) fields, instead of
mixing them with pointers (64 bits)
See you
Eric Dumazet
diff -u linux-2.6.2/fs/eventpoll.c.save linux-2.6.2/fs/eventpoll.c
--- eventpoll.c.save 2004-02-04 14:59:49.000000000 +0100
+++ eventpoll.c 2004-02-04 15:02:20.000000000 +0100
@@ -241,14 +241,15 @@
/* Number of active wait queue attached to poll operations */
int nwait;
+ /* The file descriptor this item refers to */
+ int fd;
+
/* List containing poll wait queues */
struct list_head pwqlist;
/* The "container" of this item */
struct eventpoll *ep;
- /* The file descriptor this item refers to */
- int fd;
/* The file this item refers to */
struct file *file;
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: fs/eventpoll : reduce sizeof(struct epitem)
2004-02-04 14:22 ` fs/eventpoll : reduce sizeof(struct epitem) dada1
@ 2004-02-05 4:23 ` Davide Libenzi
0 siblings, 0 replies; 18+ messages in thread
From: Davide Libenzi @ 2004-02-05 4:23 UTC (permalink / raw)
To: dada1; +Cc: Kernel Mailing List
On Wed, 4 Feb 2004, dada1 wrote:
> Hi Davide
>
> On a x86_64 platform, I noticed that the size of (struct epitem) is 136
> bytes, rounded to 192 (because of L1_CACHE alignment of 64 bytes)
>
> If you reorder some fields of this structure, we can reduce the size to
> 128 bytes.
>
> The rationale is to group nwait & fd integer (32bits) fields, instead of
> mixing them with pointers (64 bits)
Good catch. Thx I will.
- Davide
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2004-02-05 4:23 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-01 3:25 More waitpid issues with CLONE_DETACHED/CLONE_THREAD Daniel Jacobowitz
2004-02-01 4:38 ` Linus Torvalds
2004-02-01 4:43 ` Daniel Jacobowitz
2004-02-01 5:12 ` Daniel Jacobowitz
2004-02-01 21:41 ` Linus Torvalds
2004-02-01 22:25 ` Roland McGrath
2004-02-02 0:55 ` Linus Torvalds
2004-02-02 2:20 ` Andries Brouwer
2004-02-02 2:30 ` Linus Torvalds
2004-02-02 0:52 ` Daniel Jacobowitz
2004-02-02 2:41 ` Davide Libenzi
2004-02-02 2:55 ` Davide Libenzi
2004-02-04 14:22 ` fs/eventpoll : reduce sizeof(struct epitem) dada1
2004-02-05 4:23 ` Davide Libenzi
2004-02-01 5:12 ` More waitpid issues with CLONE_DETACHED/CLONE_THREAD Linus Torvalds
2004-02-01 5:14 ` Daniel Jacobowitz
2004-02-01 5:42 ` Roland McGrath
2004-02-01 5:46 ` Daniel Jacobowitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox