c: catch a segfault in exec() which was run in a child process

こ雲淡風輕ζ 提交于 2019-12-18 13:42:11

问题


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:


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.



来源:https://stackoverflow.com/questions/7339664/c-catch-a-segfault-in-exec-which-was-run-in-a-child-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!