c: catch a segfault in exec() which was ru

2019-02-07 13:43发布

EDIT:

I am trying to write a simple smoketest, where all options and reasonable parameters are tested.

I used popen() to execute the program that should be tested. Using this approach does not work, because if the process dies with a signal (SIGINT, SIGSEGV...) the pipe from popen() does not tell me what happend.

Writing a signal handler did not help since popen creates a new process that receives the signals but not my smoketest.

Thanks to the answers i used pipe(), fork() and execv() to create my own popen()-version.

When the program now segfaults there is the problem that the pipe is useless (a read caused weird behavior -> blocked the process until i send a sigkill to the parent!)

To avoid this i tried different things and my solution is the following (it is simple but it took me a while to figure it out). so here is my example-code:

static int child_dead = 0;

void sigaction_sigchld(int signal) { /* Child died */
    child_dead = 1;
}

int main(int argc, char *argv[], char *env[])
{
    char *crashing_program = "/program_path/and_name";
    int ret;
    int byte;

    pid = fork();

    if(pid == 0) /* Child */
    {
        execve(crashing_program, argv, env);

        /* if execve returns that it mus have failed! */
        fprintf(stderr, "Exec failed\n");
        _exit(-1);
    } else /* Parent */
    {
        if(!child_dead)
        {
            byte = read(pipe_out[1], line, BUFFSIZE);
            if(!byte){
                perror("Smoketest:Line:xxx");
            } else
            {
                fprintf(stdout, line);
            }
        }
        wait(&child_status);
        /*
          check if the child died with SIGSEGV etc
        */
    }

This seems to work fine as long as i only have one child at a time which is sufficient for me though. I anyone has a better idea or any tipps for me i would be glad to update this entry.

Last but not least: Of course using this method it is probably impossible to do any cleanup.

Cheers.

1条回答
闹够了就滚
2楼-- · 2019-02-07 14:10

See the documentation for waitpid(2). There are a bunch of macros you can use to test how the child process was terminated. In particular, you can use WIFSIGNALED() and WTERMSIG() to test if the child process was terminated by a signal, and if so, which signal:

int status = pclose(...);
if (WIFSIGNALED(status))
{
    // It was terminated by a signal
    if (WTERMSIG(status) == SIGSEGV)
    {
        // It was terminated by a segfault
    }
}

Edit: As stated in the comments, you'd rather make use of fork and exec, then use waitpid(2) to correctly update status.

查看更多
登录 后发表回答