views:

487

answers:

5

hi everyone, I need to intercept and trace signals from any binaries, like strace does it under linux. I don't need a so verbose output like the real one strace. I just want to know how it works, how can I intercept signal and how can I trace them. Thanks in advance :)

+2  A: 

strace uses the ptrace() system call for tracing, which also allows you to intercept (and possibly manipulate) signals sent to the process.

Here's a tiny example:

#include <sys/ptrace.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    /* simple example, child is traced, uses alarm which causes a signal to be
     * set up */
    pid_t child;

    child = fork();
    if (child == 0)
    {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        alarm(3);
        while(1)
        {
        }
        exit(0);
    }

    /* parent */
    while(1)
    {
        int wstatus;
        int signum;

        wait(&wstatus);
        if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus))
            break;

        signum = WSTOPSIG(wstatus);
        printf("child stopped with signal %d\n", signum);
        /* resume execution */
        ptrace(PTRACE_CONT, child, NULL, signum);
    }

    return 0;
}
Hasturkun
A: 

This is the simplest implementation!

Put somewhere in your int main() several calls to signal(), one for each signal you want to catch. The first argument is the signal name; the second is the signal handler function (more on that below):

    signal(SIGFPE, SignalHandler);
    signal(SIGILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    signal(SIGSEGV, SignalHandler);
    signal(SIGTERM, SignalHandler);
#ifndef WIN32
    signal(SIGHUP, SignalHandler);
    signal(SIGQUIT, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGPIPE, SignalHandler);
    signal(SIGCHLD, SignalHandler);
#endif

Now, write a signal function. It must return void and accept an int: void SignalHandler(int signal_number):

void SignalHandler(int signal_number)
{
    printf("Received signal: %s\n", strsignal(signal_number);
    // Do something
}

That's it! You can also test it by sending a signal to yourself with the function raise(SIGNAL_NAME); for example, try raise(SIGTERM);!

Andreas Bonini
A: 

Intercepting signals to other processes is something you should not do for any reason other than debugging them. This is what strace is intended for. Processes should be capable of handling their own signals.

Needless to say, if you are writing a debugger, understand ptrace().

MarkR
A: 

okay thanks for your help, but I would like to recode myself the ptrace function. so could you explain how ptrace do the job?

thanks in advance.

tegte
ptrace is a kernel supplied system call, it is not implemented in user space.
Hasturkun
A: 

yeah sorry for having mixing signals and syscalls (i assume english is not my native language and I'm not really good at). I want to develop a tool for helping me to debug my others softwares.

tegte