C:在子进程中运行的exec()中捕获段错误 [英] c: catch a segfault in exec() which was run in a child process

查看:142
本文介绍了C:在子进程中运行的exec()中捕获段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个简单的Smoketest,其中测试所有选项和合理的参数.

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

我使用popen()执行应该测试的程序. 使用这种方法是行不通的,因为如果进程死于信号(SIGINT,SIGSEGV ...),则popen()中的管道不会告诉我发生了什么.

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.

编写信号处理程序无济于事,因为popen创建了一个新进程来接收信号,但不接收我的冒烟测试.

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

由于有了答案,我使用了pipe(),fork()和execv()来创建自己的popen()版本.

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

当程序现在出现段错误时,存在管道无用的问题(读取导致奇怪的行为->阻止了该过程,直到我将sigkill发送给父级!)

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.

干杯.

推荐答案

请参见 .您可以使用许多宏来测试子进程的终止方式.特别是,您可以使用WIFSIGNALED()WTERMSIG()来测试子进程是否被信号终止,如果终止,则使用哪个信号:

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
    }
}

如评论所述,您宁愿使用fork和exec,然后使用waitpid(2)正确更新状态.

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

这篇关于C:在子进程中运行的exec()中捕获段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆