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

查看:16
本文介绍了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 创建了一个接收信号但不接收我的 smoketest 的新进程.

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
");
        _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.

干杯.

推荐答案

查看文档waitpid(2).您可以使用一堆宏来测试子进程是如何终止的.特别是,您可以使用 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天全站免登陆