c:在子进程中运行的 exec() 中捕获段错误

发布于 2024-12-03 10:57:39 字数 1412 浏览 1 评论 0原文

编辑:

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

我使用 popen() 来执行应该测试的程序。 使用这种方法不起作用,因为如果进程因信号(SIGINT、SIGSEGV...)而终止,来自 popen() 的管道不会告诉我发生了什么。

编写信号处理程序没有帮助,因为 popen 创建了一个接收信号的新进程,但不是我的烟雾测试。

感谢这些答案,我使用了 pipeline()、fork() 和 execv() 来创建我自己的 popen() 版本。

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

为了避免这种情况,我尝试了不同的方法,我的解决方案如下(这很简单,但我花了一段时间才弄清楚)。所以这是我的示例代码:

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

只要我一次只有一个孩子,这似乎就可以正常工作,但这对我来说已经足够了。如果有人对我有更好的想法或任何提示,我很乐意更新此条目。

最后但并非最不重要的一点:当然,使用这种方法可能无法进行任何清理。

干杯。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瀟灑尐姊 2024-12-10 10:57:39

请参阅 waitpid(2) 的文档。您可以使用许多宏来测试子进程是如何终止的。特别是,您可以使用 WIFSIGNALED()WTERMSIG() 来测试子进程是否被信号终止,如果是,是哪个信号:

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) 来正确更新状态。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文