【问题标题】:How to read the valgrind return value from child processes?如何从子进程中读取 valgrind 返回值?
【发布时间】:2013-11-06 21:20:34
【问题描述】:

我在 bash 脚本中运行 valgrind 以将其用于自动化测试。我已经添加了在错误时返回退出代码和跟踪子项的选项。

/usr/bin/valgrind --error-exitcode=1 --trace-children=yes ./test_prog

我的程序分叉了其他进程,我可以看到 valgrind 在终端中运行不同进程的输出。问题是,退出代码选项似乎仅在父进程出现错误时才起作用。因为即使其中一个子进程出现错误(SIGSEGV),valgrind的退出码仍然为0,这意味着它对于多个进程的自动化测试是无用的。

那么有什么选项可以让父 valgrind 捕获子错误并返回它?我已经查看了手册页。也许这个问题会有另一种解决方案,比如将孩子的输出 grep 到终端以获取任何错误消息?

提前致谢。

【问题讨论】:

    标签: linux bash valgrind


    【解决方案1】:

    在代码中实现正确的错误处理很重要。比较以下两段代码。

    答:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <signal.h>
    
    #define BUFSIZE 1024
    
    int incr=0;
    int loop=1;
    
    void runTicks(const char *n) {
        time_t t;
        char buf[BUFSIZE+1];
        pid_t pid;
        int counter;
        pid=getpid();
        counter=0;
        while(loop) {
            sleep(1);
            t=time(NULL);
            strftime(buf,BUFSIZE,"%Y.%m.%d %H:%M:%S",localtime(&t));
            printf("%s[%d] %s\n",n,pid,buf);
            counter+=incr;
            if(counter>5) memcpy((void *)1,buf,1); /* this line is for causing SEGV */
        }
    }
    
    void handler(int s) {
        if(s==SIGCHLD) {
            printf("Received SIGCHLD\n");
            loop=0;
        }
    }
    
    void setHandler() {
        struct sigaction sa;
        sa.sa_handler=handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags=SA_NOCLDSTOP;
        if(sigaction(SIGCHLD,&sa,NULL)!=0) {
            printf("Cannot set signal handler, there is no purpose in running the test\n");
            exit(0);
        }
    
    }
    
    int main() {
        pid_t pid;
        printf("start\n");
        pid=fork();
        if(pid==-1) {
            printf("fork failed\n");
            exit(10);
        }
        if(pid==0) {
            printf("child\n");
            incr=1;
            usleep(500000);
            runTicks("C");
            exit(1);
        } else {
            printf("parent spawned child pid=%d\n",pid);
            setHandler();
            runTicks("P");
            exit(0);
        }
    }
    

    乙:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <signal.h>
    #include <sys/wait.h>
    
    #define BUFSIZE 1024
    
    int incr=0;
    int loop=1;
    
    void runTicks(const char *n) {
        time_t t;
        char buf[BUFSIZE+1];
        pid_t pid;
        int counter;
        pid=getpid();
        counter=0;
        while(loop) {
            sleep(1);
            t=time(NULL);
            strftime(buf,BUFSIZE,"%Y.%m.%d %H:%M:%S",localtime(&t));
            printf("%s[%d] %s\n",n,pid,buf);
            counter+=incr;
            if(counter>5) memcpy((void *)1,buf,1); /* this line is for causing SEGV */
        }
    }
    
    void handler(int s) {
        if(s==SIGCHLD) {
            int status;
            printf("Received SIGCHLD\n");
            wait(&status);
            printf("Exit code from child: %d\n",status);
            if(status!=0) exit(status);
            loop=0;
        }
    }
    
    void setHandler() {
        struct sigaction sa;
        sa.sa_handler=handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags=SA_NOCLDSTOP;
        if(sigaction(SIGCHLD,&sa,NULL)!=0) {
            printf("Cannot set signal handler, there is no purpose in running the test\n");
            exit(0);
        }
    
    }
    
    int main() {
        pid_t pid;
        printf("start\n");
        pid=fork();
        if(pid==-1) {
            printf("fork failed\n");
            exit(10);
        }
        if(pid==0) {
            printf("child\n");
            incr=1;
            usleep(500000);
            runTicks("C");
            exit(1);
        } else {
            printf("parent spawned child pid=%d\n",pid);
            setHandler();
            runTicks("P");
            exit(0);
        }
    }
    

    在没有 valgrind 的情况下首先运行这些程序并比较两个程序的退出代码。然后在 valgrind 下运行它们并享受。

    使用这样的构造,您甚至不需要在 valgrind 下运行它来捕获子进程的段错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-09
      • 2010-12-07
      • 2018-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      相关资源
      最近更新 更多