From: Denys Vlasenko <vda.linux@googlemail.com>
To: Jan Kratochvil <jan.kratochvil@redhat.com>
Cc: Tejun Heo <tj@kernel.org>, Oleg Nesterov <oleg@redhat.com>,
Roland McGrath <roland@redhat.com>,
linux-kernel@vger.kernel.org, torvalds@linux-foundation.org,
akpm@linux-foundation.org
Subject: Re: [PATCH 1/1] ptrace: make sure do_wait() won't hang after PTRACE_ATTACH
Date: Thu, 17 Feb 2011 04:37:51 +0100 [thread overview]
Message-ID: <201102170437.51382.vda.linux@googlemail.com> (raw)
In-Reply-To: <20110216215157.GA6054@host1.dyn.jankratochvil.net>
Hi Jan,
Thanks for joining!
On Wednesday 16 February 2011 22:51, Jan Kratochvil wrote:
> On Mon, 14 Feb 2011 18:20:52 +0100, Denys Vlasenko wrote:
> > Jan, please put on your gdb maintainer's hat, we need your opinion here.
> > Is it a problem from gdb's POV?
>
> Here is a summary of current and my wished behavior:
>
> Make PTRACE_DETACH (data=SIGSTOP) working - that is to leave the process in
> `T (stopped)' without any single PC step.
This coincides of my and Oleg's desire to make SIGSTOP working with
alls ptrace restart commands.
> This works in some kernels and
> does not work in other kernels, it is "detach-stopped" test in:
> cvs -d :pserver:anoncvs:anoncvs@sourceware.org:/cvs/systemtap co ptrace-tests
>
> The current upstream GDB trick of
> PTRACE_ATTACH
> if /proc/PID/status->State: == `T (stopped)'
> tgkill(SIGSTOP)
> PTRACE_CONT(0)
> waitpid->SIGSTOP (or preceded by some other signal but 1x SIGSTOP will come)
I don't fully understand the steps of the trick.
* ptrace(PTRACE_ATTACH)
* [do you waitpid? How exactly (once? loop until SIGSTOP or ECHILD?)]
* if /proc/PID/status->State: == `T (stopped)' [why? Is it test
"was it already stopped when we attached?"
What are the other possible states?]
tgkill(SIGSTOP)
PTRACE_CONT(0)
* waitpid->SIGSTOP [What does this mean? "Loop on waitpid until SIGSTOP"?]
Moreover, I don't see the actual detaching step.
Can you describe the trick in more details?
> should remain compatible, as is implemented in:
> http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/linux-nat.c.diff?r1=1.80&r2=1.81&cvsroot=src
If I understand correctly what you are trying to do -
to inject another SIGSTOP so that DETACH won't miss it,
then a fixed ptrace which doesn't lose SIGSTOPs
will also work with the old gdb which does this trick.
The trick will be unnecessary, but it will still work.
> Make the GDB trick above no longer needed, so that in the case it was invented
> for a simple PTRACE_ATTACH, wait->SIGSTOP, PTRACE_DETACH(0) also works:
> foreign process: kill(child process, SIGSTOP)
> parent process: wait() -> SIGSTOP (the notification is now eaten-out)
> child process is now in `T (stopped)'
> debugger: PTRACE_ATTACH(child process)
> debugger: waitpid -> should get SIGSTOP, even despite it was eaten-out above
> This works in some kernels and does not work in other kernels.
I believe there is a proposal to add PTRACE_ATTACH_NOSTOP+PTRACE_INTERRUPT,
which I guess is basically PTRACE_STOP replacement which does not mess things up
with artificial SIGSTOP. Aha, I found it:
http://sourceware.org/ml/archer/2011-q1/msg00026.html
(I do not understand why PTRACE_ATTACH_NOSTOP doesn't simply
make next waitpid() return SIGTRAP stop, but maybe it makes sense
after deeper analysis... anyway, PTRACE_ATTACH_NOSTOP + PTRACE_INTERRUPT
sequence described there is not a problem to use by userspace)
This will work reliably both in above case and also for the case
where real parent did not eat yet the STOP notification.
> A new proposal is to preserve the process's `T (stopped)' for
> a naive/legacy debugger / ptrace tool doing PTRACE_ATTACH, wait->SIGSTOP,
> PTRACE_DETACH(0), incl. GDB doing the "GDB trick" above.
Right, that's the overarching idea: to preserve the stopped state
across ptrace ops.
> That is after PTRACE_DETACH(0) the process should remain `T (stopped)'
> iff the process was `T (stopped)' before PTRACE_ATTACH.
> - PTRACE_DETACH(0) should preserve `T (stopped)'.
I assume you are thinking about PTRACE_ATTACH + wait():SIGSTOP
+ PTRACE_DETACH(0) sequence.
It looks logical to use 0 in *this* sequence, but consider
the following sequence:
....
ptrace(PTRACE_CONT, 0)
waitpid(): got SIGFOO
ptrace(PTRACE_CONT/SYSCALL/DETACH, 0)
What we have here? A signal delivery notification.
In this case, in next ptrace restarting operation, we specify
whether to inject signal or not. PTRACE_DETACH is a restarting
op. SIGSTOP is a signal. Why rules for them, or their combination,
should be different? Why 0 should still inject the stop?
Basically, assuming kernel got fixed wrt loss of group-stop state,
I don't see why gdb can't simply use PTRACE_DETACH with whatever
signal it saw in last stop (using 0 if it saw non-signal stop)?
If you did see SIGSTOP delivery, pass SIGSTOP with PTRACE_DETACH,
and it will be preserved.
Regarding PTRACE_ATTACH + wait():SIGSTOP + PTRACE_DETACH(???)
sequence. I think this SIGSTOP should be considered by kernel
not to be a signal delivery ptrace stop - because this SIGSTOP
is "artificial". Therefore, next PTRACE_DETACH should ignore
its siganl parameter. IOW, it shouldn't matter whether you
use PTRACE_DETACH(0) or PTRACE_DETACH(SIGSTOP) - the stop state
should be preserved. IOW: neither SIGSTOP nor SIGCONT should
be injected. If we assume this interpretation, then PTRACE_DETACH(0)
will work correctly.
> but also:
> - PTRACE_DETACH(SIGSTOP) should force `T (stopped)'.
Of course. It should inject SIGSTOP. That stops process
(or rather, it should. You are right that now it is now
always working).
> - PTRACE_DETACH(SIGCONT) should force freely running process.
Of course. It should inject SIGCONT.
Do you need / want it to work even from a non-signal ptrace stop?
I.e. should this work too?
... ... waitpid():SIGTRAP + ptrace(PTRACE_DETACH, SIGCONT)
> The behavior of SIGSTOP and SIGCONT received during active ptrace session
> I find as a new feature without having much to keep backward compatibibility.
> +
> You have concluded a plan how to do a real `T (stopped)' on received SIGSTOP
> using PTRACE_GETSIGINFO, OK, go with that.
> +
> Personally I would keep it completely hidden from the debugger and only
> remember the last SIGCONT vs. SIGSTOP for the case the session ends with
> PTRACE_DETACH(0). Debugger/strace would not be able to display any externally
> received SIGSTOP/SIGCONT. PTRACE_CONT(SIGSTOP) and PTRACE_CONT(SIGCONT)
> should behave as PTRACE_CONT(0) to clean up compatibility with existing tools.
> For a general transparent tracing there is at least systemtap.
Again, the idea is close to what you are saying, just a bit different.
The idea is to make SIGSTOP/SIGCONT to be no different form other signals,
as far as userspace-visible ptrace API is concerned.
Thwo different ways how you end up with stopped tracee:
(1) When waitpid says that tracee got SIGSTOP, the debugger must decide, does
it want to propagate it or not. If it decides to propagate it, it does
ptrace(PTRACE_restarting_op, SIGSTOP). Which injects SIGSTOP to tracee.
If PTRACE_restarting_op == PTRACE_DETACH, the tracee is detached and stopped.
Therefore you must not use ptrace(PTRACE_DETACH, 0), it is logically wrong
if you want SIGSTOP to take effect.
(Note: there is a small twist with PTRACE_restarting_op != PTRACE_DETACH,
because the tracee is still attached and therefore it immediately reports
to debugger that it indeed has stopped in response to SIGSTOP -
which looks very similar to *SIGSTOP delivery*. For example, currently
strace is confused - it thinks that *another SIGSTOP* came in -
and issues *another* ptrace(PTRACE_SYSCALL, SIGSTOP),
which, being issued _not_ after signal delivery ptrace stop, can't inject
the SIGSTOP. Which is harmless, but confusing. Querying GETSIGINFO
can disambiguate this, and make strace output more informative. I have a patch.
But for PTRACE_DETACH it doesn't matter...)
(2) If you PTRACE_ATTACHed (or better, PTRACE_ATTACH_NOSTOP + PTRACE_INTERRUPTed,
because PTRACE_ATTACH is racy versus simultaneous SIGSTOP)
to the process which is already stopped, you don't need to do
ptrace(PTRACE_DETACH, SIGSTOP) in order to detach and leave it stopped.
Actually, if you do waitpid():SIGTRAP + ptrace(PTRACE_DETACH, <anything>),
<anything> will be ignored, because tracee is not in signal delivery ptrace stop,
so you can do ptrace(PTRACE_DETACH, SIGSTOP), no harm done:
if process was already stopped, it will remain stopped.
If it wasn't stopped, it will continue.
So, the only special trick you seem to want is to make ptrace(PTRACE_DETACH, SIGCONT)
to forcibly unpause stopped task, even if done from non-signal ptrace stop. Right?
I guess this can be special-cased, but can't the same be trivially achieved by
kill(SIGCONT) + ptrace(PTRACE_DETACH, SIGCONT)?
This will avoid the need to special case in the kernel...
--
vda
next prev parent reply other threads:[~2011-02-17 3:38 UTC|newest]
Thread overview: 160+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-28 15:08 [PATCHSET] ptrace,signal: group stop / ptrace updates Tejun Heo
2011-01-28 15:08 ` [PATCH 01/10] signal: fix SIGCONT notification code Tejun Heo
2011-01-28 15:08 ` [PATCH 02/10] ptrace: remove the extra wake_up_process() from ptrace_detach() Tejun Heo
2011-01-28 18:46 ` Roland McGrath
2011-01-31 10:38 ` Tejun Heo
2011-02-01 10:26 ` [PATCH] ptrace: use safer wake up on ptrace_detach() Tejun Heo
2011-02-01 13:40 ` Oleg Nesterov
2011-02-01 15:07 ` Tejun Heo
2011-02-01 19:17 ` Oleg Nesterov
2011-02-02 5:31 ` Roland McGrath
2011-02-02 10:35 ` Tejun Heo
2011-02-02 0:27 ` Andrew Morton
2011-02-02 5:33 ` Roland McGrath
2011-02-02 5:38 ` Andrew Morton
2011-02-02 10:34 ` Tejun Heo
2011-02-02 19:33 ` Andrew Morton
2011-02-02 20:01 ` Tejun Heo
2011-02-02 21:40 ` Oleg Nesterov
2011-02-02 5:29 ` Roland McGrath
2011-02-02 5:28 ` [PATCH 02/10] ptrace: remove the extra wake_up_process() from ptrace_detach() Roland McGrath
2011-01-28 15:08 ` [PATCH 03/10] signal: remove superflous try_to_freeze() loop in do_signal_stop() Tejun Heo
2011-01-28 18:46 ` Roland McGrath
2011-01-28 15:08 ` [PATCH 04/10] ptrace: kill tracehook_notify_jctl() Tejun Heo
2011-01-28 21:09 ` Roland McGrath
2011-01-28 15:08 ` [PATCH 05/10] ptrace: add @why to ptrace_stop() Tejun Heo
2011-01-28 18:48 ` Roland McGrath
2011-01-28 15:08 ` [PATCH 06/10] signal: fix premature completion of group stop when interfered by ptrace Tejun Heo
2011-01-28 21:22 ` Roland McGrath
2011-01-31 11:00 ` Tejun Heo
2011-02-02 5:44 ` Roland McGrath
2011-02-02 10:56 ` Tejun Heo
2011-01-28 15:08 ` [PATCH 07/10] signal: use GROUP_STOP_PENDING to stop once for a single group stop Tejun Heo
2011-01-28 15:08 ` [PATCH 08/10] ptrace: participate in group stop from ptrace_stop() iff the task is trapping for " Tejun Heo
2011-01-28 21:30 ` Roland McGrath
2011-01-31 11:26 ` Tejun Heo
2011-02-02 5:57 ` Roland McGrath
2011-02-02 10:53 ` Tejun Heo
2011-02-03 10:02 ` Tejun Heo
2011-02-01 19:36 ` Oleg Nesterov
2011-01-28 15:08 ` [PATCH 09/10] ptrace: make do_signal_stop() use ptrace_stop() if the task is being ptraced Tejun Heo
2011-01-28 15:08 ` [PATCH 10/10] ptrace: clean transitions between TASK_STOPPED and TRACED Tejun Heo
2011-02-03 20:41 ` [PATCH 0/1] (Was: ptrace: clean transitions between TASK_STOPPED and TRACED) Oleg Nesterov
2011-02-03 20:41 ` [PATCH 1/1] ptrace: make sure do_wait() won't hang after PTRACE_ATTACH Oleg Nesterov
2011-02-03 21:36 ` Roland McGrath
2011-02-03 21:44 ` Oleg Nesterov
2011-02-04 10:53 ` Tejun Heo
2011-02-04 13:04 ` Oleg Nesterov
2011-02-04 14:48 ` Tejun Heo
2011-02-04 17:06 ` Oleg Nesterov
2011-02-05 13:39 ` Tejun Heo
2011-02-07 13:42 ` Oleg Nesterov
2011-02-07 14:11 ` Tejun Heo
2011-02-07 15:37 ` Oleg Nesterov
2011-02-07 16:31 ` Tejun Heo
2011-02-07 17:48 ` Oleg Nesterov
2011-02-09 14:18 ` Tejun Heo
2011-02-09 14:21 ` Tejun Heo
2011-02-09 21:25 ` Oleg Nesterov
2011-02-13 23:01 ` Denys Vlasenko
2011-02-14 9:03 ` Jan Kratochvil
2011-02-14 11:39 ` Denys Vlasenko
2011-02-14 17:32 ` Oleg Nesterov
2011-02-14 16:01 ` Oleg Nesterov
2011-02-26 3:59 ` Pavel Machek
2011-02-14 15:51 ` Oleg Nesterov
2011-02-14 14:50 ` Tejun Heo
2011-02-14 18:53 ` Oleg Nesterov
2011-02-13 22:25 ` Denys Vlasenko
2011-02-14 15:13 ` Tejun Heo
2011-02-14 16:15 ` Oleg Nesterov
2011-02-14 16:33 ` Tejun Heo
2011-02-14 17:23 ` Oleg Nesterov
2011-02-14 17:20 ` Denys Vlasenko
2011-02-14 17:30 ` Tejun Heo
2011-02-14 17:45 ` Oleg Nesterov
2011-02-14 17:54 ` Denys Vlasenko
2011-02-21 15:16 ` Tejun Heo
2011-02-21 15:28 ` Oleg Nesterov
2011-02-21 16:11 ` [pseudo patch] ptrace should respect the group stop Oleg Nesterov
2011-02-22 16:24 ` [PATCH 1/1] ptrace: make sure do_wait() won't hang after PTRACE_ATTACH Tejun Heo
2011-02-24 21:08 ` Oleg Nesterov
2011-02-25 15:45 ` Tejun Heo
2011-02-25 17:42 ` Roland McGrath
2011-02-28 15:23 ` Oleg Nesterov
2011-02-14 17:51 ` Oleg Nesterov
2011-02-14 18:55 ` Denys Vlasenko
2011-02-14 19:01 ` Oleg Nesterov
2011-02-14 19:42 ` Denys Vlasenko
2011-02-14 20:01 ` Oleg Nesterov
2011-02-15 15:24 ` Tejun Heo
2011-02-15 15:58 ` Oleg Nesterov
2011-02-15 17:31 ` Roland McGrath
2011-02-15 20:27 ` Oleg Nesterov
2011-02-18 17:02 ` Tejun Heo
2011-02-18 19:37 ` Oleg Nesterov
2011-02-21 16:22 ` Tejun Heo
2011-02-21 16:49 ` Oleg Nesterov
2011-02-21 16:59 ` Tejun Heo
2011-02-23 19:31 ` Oleg Nesterov
2011-02-25 15:10 ` Tejun Heo
2011-02-24 20:29 ` Oleg Nesterov
2011-02-25 15:51 ` Tejun Heo
2011-02-26 2:48 ` Denys Vlasenko
2011-02-28 12:56 ` Tejun Heo
2011-02-28 13:16 ` Denys Vlasenko
2011-02-28 13:29 ` Tejun Heo
2011-02-28 13:41 ` Denys Vlasenko
2011-02-28 13:53 ` Tejun Heo
2011-02-28 14:25 ` Denys Vlasenko
2011-02-28 14:39 ` Tejun Heo
2011-02-28 16:48 ` Oleg Nesterov
2011-02-28 14:36 ` Oleg Nesterov
2011-02-16 21:51 ` Jan Kratochvil
2011-02-17 3:37 ` Denys Vlasenko [this message]
2011-02-17 19:19 ` Oleg Nesterov
2011-02-18 21:11 ` Jan Kratochvil
2011-02-19 20:16 ` Oleg Nesterov
2011-02-17 16:49 ` Oleg Nesterov
2011-02-17 18:58 ` Roland McGrath
2011-02-17 19:33 ` Oleg Nesterov
2011-02-18 21:34 ` Jan Kratochvil
2011-02-19 20:06 ` Oleg Nesterov
2011-02-20 9:40 ` Jan Kratochvil
2011-02-20 17:06 ` Denys Vlasenko
2011-02-20 17:48 ` Oleg Nesterov
2011-02-20 19:10 ` Jan Kratochvil
2011-02-20 19:16 ` Oleg Nesterov
2011-02-20 17:16 ` Oleg Nesterov
2011-02-20 18:52 ` Jan Kratochvil
2011-02-20 20:38 ` Oleg Nesterov
2011-02-20 21:06 ` `(T) stopped' preservation after _exit() [Re: [PATCH 1/1] ptrace: make sure do_wait() won't hang after PTRACE_ATTACH] Jan Kratochvil
2011-02-20 21:19 ` Oleg Nesterov
2011-02-20 21:20 ` [PATCH 1/1] ptrace: make sure do_wait() won't hang after PTRACE_ATTACH Jan Kratochvil
2011-02-21 14:23 ` Oleg Nesterov
2011-02-23 16:44 ` Jan Kratochvil
2011-02-14 15:31 ` Oleg Nesterov
2011-02-14 17:24 ` Denys Vlasenko
2011-02-14 17:39 ` Oleg Nesterov
2011-02-14 17:57 ` Denys Vlasenko
2011-02-14 18:00 ` Oleg Nesterov
2011-02-14 18:06 ` Oleg Nesterov
2011-02-14 18:59 ` Denys Vlasenko
2011-02-13 21:24 ` Denys Vlasenko
2011-02-14 15:06 ` Oleg Nesterov
2011-02-14 15:19 ` Tejun Heo
2011-02-14 16:20 ` Oleg Nesterov
2011-02-14 17:05 ` Denys Vlasenko
2011-02-14 17:18 ` Oleg Nesterov
2011-01-28 16:54 ` [PATCHSET] ptrace,signal: group stop / ptrace updates Ingo Molnar
2011-01-28 17:41 ` Thomas Gleixner
2011-01-28 18:04 ` Anca Emanuel
2011-01-28 18:36 ` Mathieu Desnoyers
2011-01-28 17:55 ` Oleg Nesterov
2011-01-28 18:29 ` Bash not reacting to Ctrl-C Ingo Molnar
2011-02-05 20:34 ` Oleg Nesterov
2011-02-07 13:08 ` Oleg Nesterov
2011-02-09 6:17 ` Michael Witten
2011-02-09 14:53 ` Ingo Molnar
2011-02-09 19:37 ` Michael Witten
2011-02-11 14:41 ` Pavel Machek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201102170437.51382.vda.linux@googlemail.com \
--to=vda.linux@googlemail.com \
--cc=akpm@linux-foundation.org \
--cc=jan.kratochvil@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=oleg@redhat.com \
--cc=roland@redhat.com \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox