Question

I am building a simple debugger for my university class and I have a problem in handling SIGINT.

What I want to do is when the debugger process (from now on PDB) takes a SIGINT signal passes that to the child process (the one that is being actually debugged by PDB).

I am doing this:

pid_t childid;

void catch_sigint(int sig)
{
    signal(SIGINT,SIG_DFL);
    kill(childid,sig);
}

int debuger (char *address, parm *vars)
{
    int ignore=1;
    int status;

    childid = fork();
    signal(SIGINT,catch_sigint);
    if(childid==0)
    {
        ptrace(PTRACE_TRACEME,0, NULL,NULL);
        if(execve(address,NULL,NULL)==-1)
        {
            perror("ERROR occured when trying to create program to trace\n");
            exit(1);
        }
    }
    else
    {
        int f_time=1;

        while(1)
        {
            long system_call;

            wait(&status);
            if(WIFEXITED(status))break;
            if(WIFSIGNALED(status))break;

            system_call = ptrace(PTRACE_PEEKUSER,childid, 4 * ORIG_EAX, NULL);

            if(!strcmp(vars->category,"process-control") || !strcmp(vars->category,"all"))      
                ignore = pr_calls(system_call,ignore,limit,childid,vars->mode); //function that takes the system call that is made and prints info about it
            if(!strcmp(vars->category,"file-management") || !strcmp(vars->category,"all"))
                ignore = fl_calls(system_call,ignore,limit,childid,vars->mode);

            if(f_time){ignore=1;f_time=0;}
            ptrace(PTRACE_SYSCALL,childid, NULL, NULL);
        }        
    }
    signal(SIGINT,SIG_DFL);
    return 0;
}

This program runs and forks a child process and execs a program to trace its system calls. That works fine when it doesn't get any signal.

But when in the middle of some tracing I press ctrl+c I expect the child process to stop and PDB to continue and stop (because of this line if(WIFSIGNALED(status))break;. That never happens. The program it traces continues its system calls and prints.

The tracing program is that:

#include <stdio.h>

int main(void)
{
    for(;;) printf("HELLO WORLD\n");        
    return 0;
}

That program continues printing HELLO WORLD even after I hit ctrl+c.

I also observed that the system calls that ptrace gives after ctrl+c are -38 and that the status in wait changes only once after the signal from 1407 (I think is the normal value) to 639 and then back again to 1407 on the next wait.

So what I am doing wrong in that?

Était-ce utile?

La solution

The problem it's on this line:

ptrace(PTRACE_SYSCALL,childid, NULL, NULL);

It has to be like that:

ptrace(PTRACE_SYSCALL,childid, NULL, signal_variable);

Where signal_variable is an int declared in global scope so the handler and the debugger can see it. It has a starting value of 0.

The signal handler now takes the signal and passes it in this variable and at the next loop when the ptrace orders the tracee program to continue it sends it the signal too. That happens because when you trace a program the tracee stops execution when it receives a signal and waits further instruction for what to do with the signal from the tracer through ptrace.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top