On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote:
> On 10/05, Jan Kratochvil wrote:
> >
> > On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote:
> > > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX)
> > > and then another/same tracer does ptrace(ATTACH, tracee)
> > > then SIGXXX will not be reported to the new tracer.
> > >
> > > Why?
> >
> > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP.
> 
> They should not, this is just wrong.

That may be a right point but such programs are in use out there.  Sure if it
would be a real difficulty one can keep it as-is as GDB-7.0 soon to be
released has it already fixed, strace works with it.  Still ltrace crashes the
inferior in such case.


> And I think the proposed change doesn't change the behaviour
> in this sense.

We started to discuss two different changes:

my asked for one: ptrace(DETACH, SIGSTOP) should leave the tracee stopped.

a new one: First signal after PTRACE_ATTACH should be SIGSTOP.

I find the latter as a lower priority, it just was brought in as a part of the
discussion.  I am not aware the latter would be any time filed as a real Bug.


> > > It is not trivial to implement, and I don't understand why
> > > it is important to keep this behaviour. But we have the test
> > > case which checks this: attach-into-signal.
> >
> > This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the
> > first one after PTRACE_ATTACH.  It has specific handling of such cases.
> 
> This test-case also does:
> 
>       /* detach with SIGPIPE/attach. This should kill tracee */
>       ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE);
> 
>       ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0);
> 
>       waitpid (child, &status, 0);
>       assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE);
> 
> It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what
> I can't understand.

attach-info-signal from the ptrace-testsuite does not FAIL for me.  Which
kernel version does it FAIL on for you?



> > > Could you explain what can be breaked if SIGXXX will be reported
> > > to the next tracer (assuming the 2nd ATTACH is fast enough) ?
> >
> > With a testcase looping in: void handler(int sig) { raise(sig); }:
> > the latest official GDB release (6.8) will:
> >
> > Attaching to process 5412
> > linux-nat.c:988: internal-error: linux_nat_attach: Assertion `pid == GET_PID
> > (inferior_ptid) && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP'
> > failed.
> > A problem internal to GDB has been detected,
> > further debugging may prove unreliable.
> > Quit this debugging session? (y or n) y
> 
> Hmm. Could you please explain what "testcase looping" above mean?

Attached.


> Perhaps we don't understand each other...
> 
> OK. Currently, ptrace(DETACH, SIGXXX) means:
> 
>       - untrace
> 
>       - the tracee will get this SIGXXX and handle this signal
> 
>       - BUT! if the new tracer attaches right now, before the
>         tracee handles the signal, this signal will not be
>         reported to the new tracer.
> 
> With the current utrace-ptrace implementation: if the second
> attach happens before the tracee dequeues SIGXXX, this signal
> will be reported to the new tracer too.

I think you are discussing the latter Bug (first signal received by a tracer
after PTRACE_ATTACH should be SIGSTOP) while I was asking about the former
Bug (PTRACE_DETACH(SIGSTOP) should leave tracee stopped), do you agree?


Thanks,
Jan
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <assert.h>

#define SIGNAL SIGALRM

static void
handler (int sig)
{
  raise (sig);
}

int
main (void)
{
  struct sigaction act;
  int i;

  memset (&act, 0, sizeof (struct sigaction));
  act.sa_handler = handler;
  act.sa_flags = SA_RESTART;
  i = sigaction (SIGNAL, &act, 0);
  assert (i == 0);

  i = raise (SIGNAL);
  assert (i == 0);
  assert (0);

  return 0;
}

Reply via email to