List Info

Thread: expected behavior when a signal is sent to the ptraced child




expected behavior when a signal is sent to the ptraced child
user name
2006-05-25 02:36:37
Who will get the signal, the child, or the parent? or
neither?

The manual of ptrace says like this:

   While being traced, the child will stop each time a
signal is delivered, 
   even if the signal is being ignored.  (The  exception  is
SIGKILL,  
   which  has its usual effect.)  The parent will be
notified at its next 
   wait and may inspect and modify the child process while
it is stopped.
   The parent then causes the child to continue, optionally
ignoring the
   delivered signal (or even  delivering a different signal
instead).

My reading is that it is still the child who will get the
signal, but it 
won't call its signal handler as it usually does.

It will stop instead. then the wait function of the prarent
(in our case, 
GDB) will return and get the control. It can inspect the
status of the 
child and know what cause the child to stop.  Then gdb can
let the child
continue using PTRACE_CONT, in this it can choose to delieve
the signal on 
to the child, and also ignore it, and even deliver a
different signal.

If my understanding is correct. Then a follow up question is
how to make 
the child not to call its signal handler and to stop
instead.  The reason 
I ask this is that with one kernel, I get different result
than the above
with the following test code:

linux # cat trap-handle.c
#include <sys/types.h>
#include <unistd.h>
#include "../include/asm-ppc/ptrace.h"
#include <linux/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <linux/user.h>
#include <signal.h>
#include <errno.h>
#include <sys/ucontext.h>

#define PTRACE_SET_DEBUGREG 26
#define PTRACE_GET_DEBUGREG 25

unsigned long debug;
    struct sigaction s;

static void myhandler (unsigned int sn , siginfo_t  *si,
struct ucontext_t 
*sc)
{
   unsigned int mnip;
   int i;
   
   printf("In Trap handler ************ \n");
   printf(" signal number = %d, signal errno = %d,
signal code = %d, signal address = %x\n",
            si->si_signo,si->si_errno,si->si_code,
si->si_addr);
}

int main()
{
    unsigned long bptaddr = 0;
    pid_t child;

    sigemptyset(&s.sa_mask);   //sa_mask = 0;
    s.sa_flags = SA_SIGINFO;
    s.sa_sigaction = (void *)myhandler;
    if (sigaction (SIGTRAP,&s,(struct sigaction *)NULL))
{
      printf("Sigaction returned error = %d\n",
errno);
     exit(0);
   }


    child = fork();
    if(child == 0) {
        printf("Hi, I'm the Child \n");
        printf("child entry, waiting a little
bit\n");
        sleep(5);
        printf("child pid = %x
%d\n",getpid(),getpid());
        debug = getpid() - 4;
        printf("child leaving, debug = %d \n",
debug);
    }
    else {

        int status;
        pid_t w;
        int rc = -100;

        ptrace(PTRACE_ATTACH, child, NULL, NULL);
        wait(NULL);
        printf("Parent now has control \n");
        printf("parent pid = %x
%d\n",getpid(),getpid());
        if (rc =
ptrace(PTRACE_SET_DEBUGREG,child,0,&debug))
          printf ("set debugreg return non-zero:
%d\n", rc);
        else
          printf ("set debugreg return
zero\n");
        ptrace(PTRACE_CONT, child, NULL, NULL);
        w =  wait(&status);
        if (w == -1) { perror("waitpid");
exit(-10); }
        if (WIFEXITED(status)) {
             printf("exited, status=%d\n",
WEXITSTATUS(status));
        } else if (WIFSIGNALED(status)) {
             printf("killed by signal %d\n",
WTERMSIG(status));
        } else if (WIFSTOPPED(status)) {
             printf("stopped by signal %d\n",
WSTOPSIG(status));
        } else {
            printf("not sure what reason\n");
        }

        ptrace(PTRACE_DETACH, child, NULL, NULL);
        printf("debug = %d \n",debug);
    }
    return 0;
}

The output of running the executable is like this:

linux # ./trap-handle
Parent now has control
parent pid = 151a 5402
set debugreg return zero
Hi, I'm the Child
child entry, waiting a little bit
child pid = 151b 5403
In Trap handler ************
 signal number = 5, signal errno = 0, signal code = 4,
signal address = 
1001110c
child leaving, debug = 5399
exited, status=0
debug = 0
# 

What I expect is the parent will at least output:

stopped by signal 5 

What is the  problem here?  Did I make something wrong? 
Please correct me 
if there are anything wrong!  Thanks a lot!

Regards
- Wu Zhou
expected behavior when a signal is sent to the ptraced child
user name
2006-05-25 03:29:39
On Thu, May 25, 2006 at 10:36:37AM +0800, Wu Zhou wrote:
> It will stop instead. then the wait function of the
prarent (in our case, 
> GDB) will return and get the control. It can inspect
the status of the 
> child and know what cause the child to stop.  Then gdb
can let the child
> continue using PTRACE_CONT, in this it can choose to
delieve the signal on 
> to the child, and also ignore it, and even deliver a
different signal.

Yes.

> If my understanding is correct. Then a follow up
question is how to make 
> the child not to call its signal handler and to stop
instead.  The reason 
> I ask this is that with one kernel, I get different
result than the above
> with the following test code:

If the child receives a signal, it will stop.  It looks to
me as if
your kernel is not generating the signal in the normal way,
i.e.
somehow bypassing normal delivery.

-- 
Daniel Jacobowitz
CodeSourcery
expected behavior when a signal is sent to the ptraced child
user name
2006-05-25 03:50:36
Hi Daniel,

On Wed, 24 May 2006, Daniel Jacobowitz wrote:

> On Thu, May 25, 2006 at 10:36:37AM +0800, Wu Zhou
wrote:
> > It will stop instead. then the wait function of
the prarent (in our case, 
> > GDB) will return and get the control. It can
inspect the status of the 
> > child and know what cause the child to stop.  Then
gdb can let the child
> > continue using PTRACE_CONT, in this it can choose
to delieve the signal on 
> > to the child, and also ignore it, and even deliver
a different signal.
> 
> Yes.

Thanks for the confirmation.

> 
> > If my understanding is correct. Then a follow up
question is how to make 
> > the child not to call its signal handler and to
stop instead.  The reason 
> > I ask this is that with one kernel, I get
different result than the above
> > with the following test code:
> 
> If the child receives a signal, it will stop.  It looks
to me as if
> your kernel is not generating the signal in the normal
way, i.e.
> somehow bypassing normal delivery.

In this testcase, the child enters into the signal handler
and then it 
continues its execution until its end.  The parent get the
control then.

I guess you are right, the kernel guy I am working with
might use a 
non-normal way to generate the signal.  I need to confirm
with him about 
that though.

Thanks for your quick answer!
- Wu Zhou
expected behavior when a signal is sent to the ptraced child
user name
2006-05-25 09:06:43
Wu Zhou <woodzltccn.ibm.com> writes:

> What I expect is the parent will at least output:
>
> stopped by signal 5 
>
> What is the  problem here?  Did I make something wrong?

You need to use waitpid/wait4 and add WUNTRACED to the
options parameter.
Without that you'll never receive notification of stopped
processes.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwabsuse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg,
Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5
214B 8276 4ED5
"And now for something completely different."
expected behavior when a signal is sent to the ptraced child
user name
2006-05-25 13:06:05
On Thu, May 25, 2006 at 11:06:43AM +0200, Andreas Schwab
wrote:
> Wu Zhou <woodzltccn.ibm.com> writes:
> 
> > What I expect is the parent will at least output:
> >
> > stopped by signal 5 
> >
> > What is the  problem here?  Did I make something
wrong?
> 
> You need to use waitpid/wait4 and add WUNTRACED to the
options parameter.
> Without that you'll never receive notification of
stopped processes.

WUNTRACED shouldn't be necessary in this case because the
child is
actually ptraced.

-- 
Daniel Jacobowitz
CodeSourcery
expected behavior when a signal is sent to the ptraced child
user name
2006-05-26 02:22:11
On Thu, 25 May 2006, Daniel Jacobowitz wrote:

> On Thu, May 25, 2006 at 11:06:43AM +0200, Andreas
Schwab wrote:
> > Wu Zhou <woodzltccn.ibm.com> writes:
> > 
> > > What I expect is the parent will at least
output:
> > >
> > > stopped by signal 5 
> > >
> > > What is the  problem here?  Did I make
something wrong?
> > 
> > You need to use waitpid/wait4 and add WUNTRACED to
the options parameter.
> > Without that you'll never receive notification of
stopped processes.
> 
> WUNTRACED shouldn't be necessary in this case because
the child is
> actually ptraced.

I guess Daniel is right.  the manual of wait/waitpid says
this about 
WUNTRACED:
  also  return if  a  child  has  stopped  (but  not  traced
 via
  ptrace).  Status for traced children which  have  stopped 
is
  provided even if this option is not specified.

In the testcase, I use PTRACE_ATTACH to trace the child. So
WUNTRACED is 
not needed here.  

Thank you anyway!  At least I learned that there is a
WUNTRACED option 
to change the behavior of the delivery of a signal. it lets
the child 
stop without tracing it.  A good feature indeed, right?

Regards
- Wu Zhou

P.S: it seems that my mail agent have some problems when
connecting from 
home. It sent a couple repeated message.  Sorry for that!
[1-6]

about | contact  Other archives ( Real Estate discussion Medical topics )