From: "Indan Zupancic" <indan@nul.nu>
To: "Tejun Heo" <tj@kernel.org>
Cc: "Denys Vlasenko" <vda.linux@googlemail.com>,
"Oleg Nesterov" <oleg@redhat.com>,
"Roland McGrath" <roland@redhat.com>,
jan.kratochvil@redhat.com, linux-kernel@vger.kernel.org,
torvalds@linux-foundation.org, akpm@linux-foundation.org
Subject: Re: [RFC] Proposal for ptrace improvements
Date: Wed, 2 Mar 2011 12:32:36 +0100 (CET) [thread overview]
Message-ID: <6b211a19ed02fa7f001343fbd8e3d5a9.squirrel@webmail.greenhost.nl> (raw)
In-Reply-To: <20110302074447.GE19669@htj.dyndns.org>
On Wed, March 2, 2011 08:44, Tejun Heo wrote:
> On Wed, Mar 02, 2011 at 06:07:35AM +0100, Indan Zupancic wrote:
>> I'm not sure what Denys is talking about: Currently it's impossible to
>> pass along SIGSTOP to traced processes. Quoting the ptrace manpage:
>>
>> PTRACE_CONT
>> Restarts the stopped child process. If data is nonzero and not
>> SIGSTOP, it is interpreted as a signal to be delivered to the
>> child; otherwise, no signal is delivered.
>
> AFAICS, that's not true. SIGSTOP isn't treated differently from other
> signals in the ptrace signal delivery path. Maybe it was true in the
> past.
Well, I can't find it in the code either, but it's probably a side-effect
of how ptrace is currently implemented. Test program code below, see for
yourself. I hope it's a program bug, but perhaps it's a kernel bug, as I
seem to get two SIGSTOP events when I allow the SIGSTOP, but only one when
denying it. In both cases the traced process isn't actually stopped.
What might happen is that, because the current code handles the traced
task as stopped, the new SIGSTOP signal is first added and then cleared
when the task continues. This doesn't explain the double SIGSTOP
notifications, I'd expect it to either loop indefinitely or to not
notify the SIGSTOP twice.
>> As for distinguishing STOP signals from stopped childs: Just don't set
>> the WUNTRACED flag in the tracer for waitpid.
>
> I'm not following. Can you please elaborate?
Sorry, should have quoted Denys:
This proposal adds a new rule for handling of stop notification
by debuggers. Let's spell it out, because currently strace
doesn't act according to this new rule:
"When waitpid indicates stop on a *stop* signal, then it may be either:
* a signal delivery (strace will inject this signal with PTRACE_SYSCALL(sig));
* or it may be a stop notification, in which case strace *must not*
try to inject this signal (this would be a bug, it'd make task running).
Instead, strace should just go back to waiting in waitpid().
These two possibilities can be distinquished by querying
PTRACE_GETSIGINFO. On stop notifications, PTRACE_GETSIGINFO
errors out - stop notification is not a signal delivery
and therefore it has no siginfo."
End quote.
You don't get the second case when not setting the WUNTRACED flag.
>> To me it seems clear that job ctl state should be managed independently
>> of ptrace stopped state. I'm not sure how that fits in with your
>> proposed changes, but my impression is that you make everything a lot
>> simpler by separating traced stopping/continuing from SIGSTOP/SIGCONT
>> job control. It's just not the same. A task stopped by a trace event
>> shouldn't generate a STOP signal for it's parent, only for real SIGSTOPS.
>
> Again, not following. In the proposal, job control and ptrace operate
> independently, so on that we seem to agree, but I can't understand
> where the STOP signal for the parent comes from? What are you
> referring to?
What I mean is, if you have a parent P with a child C, and C is ptraced by T,
P shouldn't get SIGSTOP notifications when it waits for C with WUNTRACED set
and C is stopped because of a ptrace event.
Greetings,
Indan
---
Test program:
#include <errno.h>
#include <sched.h> /* clone */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/stat.h>
typedef enum event_type
{
EVENT_NONE,
EVENT_INTR,
EVENT_SIG,
EVENT_EXIT,
} event_t;
struct event
{
event_t type;
int pid;
int num;
};
int trace_fork(void);
event_t trace_event(struct event* e);
void event_allow(struct event* e);
void event_deny(struct event* e);
static void event_end(struct event* e, int deny);
int trace_fork(void)
{
int pid;
int ret;
fflush(NULL);
pid = fork();
/* child */
if (pid == 0){
ret = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
if (ret)
perror("ptrace");
return 0;
}
/* parent process */
return pid;
}
static void event_end(struct event* e, int deny)
{
int ret;
event_t type = e->type;
long sig = 0;
switch (type) {
case EVENT_NONE:
case EVENT_INTR:
case EVENT_EXIT:
return;
case EVENT_SIG:
if (!deny)
sig = e->num;
break;
}
/* continue the stopped child, sending signal 'sig' */
ret = ptrace(PTRACE_SYSCALL, e->pid, NULL, (void*)sig);
if (ret)
perror("event_end");
}
void event_allow(struct event* e)
{
event_end(e, 0);
}
void event_deny(struct event* e)
{
event_end(e, 1);
}
event_t trace_event(struct event* e)
{
long pid;
int status, sig;
retry:
memset(e, 0, sizeof(*e));
// pid = waitpid(-1, &status, __WALL);
pid = wait(&status);
if (pid == -1){
if (errno == EINTR){
e->type = EVENT_INTR;
return EVENT_INTR;
}
/* We've no child processes left */
return EVENT_NONE;
}
e->pid = pid;
if (!WIFSTOPPED(status)){
e->type = EVENT_EXIT;
if (WIFEXITED(status)){
e->num = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)){
e->num = WTERMSIG(status) + 128;
} else {
/* Don't send SIGCHLD signals up */
goto retry;
}
return EVENT_EXIT;
}
e->type = EVENT_SIG;
sig = WSTOPSIG(status);
switch (sig){
case SIGTRAP:
/* Don't kill the prisoner by sending it SIGTRAP */
event_deny(e);
/* Don't sent SIGTRAP events up */
goto retry;
default:
/* Signal */
e->num = sig;
}
return e->type;
}
int main(int argc, char* argv[])
{
struct event e;
int pid;
pid = trace_fork();
if (pid < 0){
perror("trace_fork");
return errno;
} else if (pid == 0){
/* Child */
while (1){
sleep(2);
printf("Still running!\n");
}
return 0;
}
/* Tracer */
printf("New child %d\n", pid);
while (1){
int event = trace_event(&e);
if (event == EVENT_NONE)
return 0;
if (event == EVENT_SIG)
printf("Got signal %d\n", e.num);
event_allow(&e);
}
return 0;
}
next prev parent reply other threads:[~2011-03-02 11:32 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-01 15:24 Tejun Heo
2011-03-01 16:57 ` Denys Vlasenko
2011-03-01 17:09 ` Tejun Heo
2011-03-01 17:12 ` Tejun Heo
2011-03-01 17:21 ` Denys Vlasenko
2011-03-01 18:34 ` Tejun Heo
2011-03-01 23:51 ` Denys Vlasenko
2011-03-02 7:10 ` Tejun Heo
2011-03-02 5:07 ` Indan Zupancic
2011-03-02 7:44 ` Tejun Heo
2011-03-02 11:32 ` Indan Zupancic [this message]
2011-03-02 11:52 ` Denys Vlasenko
2011-03-02 14:50 ` Tejun Heo
2011-03-02 13:32 ` Oleg Nesterov
2011-03-03 0:47 ` Indan Zupancic
2011-03-03 1:30 ` Denys Vlasenko
2011-03-03 1:55 ` Indan Zupancic
2011-03-03 7:03 ` Tejun Heo
2011-03-01 19:06 ` Jan Kratochvil
2011-03-01 22:14 ` Denys Vlasenko
2011-03-02 7:28 ` Tejun Heo
2011-03-02 10:58 ` Denys Vlasenko
2011-03-04 16:14 ` Jan Kratochvil
2011-03-04 16:41 ` Denys Vlasenko
2011-03-04 17:07 ` Oleg Nesterov
2011-03-04 18:12 ` Jan Kratochvil
2011-03-05 8:47 ` Tejun Heo
2011-03-01 22:59 ` Denys Vlasenko
2011-03-02 7:32 ` Tejun Heo
2011-03-02 11:02 ` Denys Vlasenko
2011-03-02 11:23 ` Tejun Heo
2011-03-03 19:26 ` Oleg Nesterov
2011-03-01 23:16 ` Denys Vlasenko
2011-03-02 7:37 ` Tejun Heo
2011-03-02 11:21 ` Denys Vlasenko
2011-03-02 11:27 ` Tejun Heo
2011-03-02 11:48 ` Denys Vlasenko
2011-03-02 14:43 ` Tejun Heo
2011-03-02 15:16 ` Denys Vlasenko
2011-03-02 15:25 ` Tejun Heo
2011-03-03 17:34 ` Oleg Nesterov
2011-03-03 20:22 ` Oleg Nesterov
2011-03-04 8:23 ` Tejun Heo
2011-03-04 18:16 ` Oleg Nesterov
2011-03-05 8:33 ` Tejun Heo
2011-03-04 13:01 ` Denys Vlasenko
2011-03-04 13:41 ` Tejun Heo
2011-03-04 13:59 ` Denys Vlasenko
2011-03-04 14:07 ` Tejun Heo
2011-03-04 14:31 ` Denys Vlasenko
2011-03-04 14:40 ` Tejun Heo
2011-03-04 17:05 ` Denys Vlasenko
2011-03-04 17:12 ` Linus Torvalds
2011-03-04 18:59 ` Denys Vlasenko
2011-03-04 19:24 ` Linus Torvalds
2011-03-04 16:13 ` Oleg Nesterov
2011-03-04 16:30 ` Oleg Nesterov
2011-03-04 8:44 ` Tejun Heo
2011-03-04 16:01 ` Oleg Nesterov
2011-03-04 16:15 ` Tejun Heo
2011-03-04 16:26 ` Oleg Nesterov
2011-03-07 15:08 ` PTRACE_SEIZE/INTERRUPT: " Oleg Nesterov
2011-03-09 9:41 ` Tejun Heo
2011-03-09 17:30 ` Oleg Nesterov
2011-03-07 20:43 ` Roland McGrath
2011-03-09 10:28 ` Tejun Heo
2011-03-10 18:33 ` Steven Rostedt
2011-03-11 8:13 ` Tejun Heo
2011-03-11 8:22 ` Ingo Molnar
2011-03-11 9:35 ` Srikar Dronamraju
2011-03-11 9:43 ` Ingo Molnar
2011-03-14 1:03 ` Frank Ch. Eigler
2011-03-10 15:55 ` Steven Rostedt
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=6b211a19ed02fa7f001343fbd8e3d5a9.squirrel@webmail.greenhost.nl \
--to=indan@nul.nu \
--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 \
--cc=vda.linux@googlemail.com \
/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
all inboxes | Powered by JetHome®