如何从子进程读取 valgrind 返回值



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

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

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

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

提前谢谢。

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

一个:

#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] %sn",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 SIGCHLDn");
        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 testn");
        exit(0);
    }
}
int main() {
    pid_t pid;
    printf("startn");
    pid=fork();
    if(pid==-1) {
        printf("fork failedn");
        exit(10);
    }
    if(pid==0) {
        printf("childn");
        incr=1;
        usleep(500000);
        runTicks("C");
        exit(1);
    } else {
        printf("parent spawned child pid=%dn",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] %sn",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 SIGCHLDn");
        wait(&status);
        printf("Exit code from child: %dn",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 testn");
        exit(0);
    }
}
int main() {
    pid_t pid;
    printf("startn");
    pid=fork();
    if(pid==-1) {
        printf("fork failedn");
        exit(10);
    }
    if(pid==0) {
        printf("childn");
        incr=1;
        usleep(500000);
        runTicks("C");
        exit(1);
    } else {
        printf("parent spawned child pid=%dn",pid);
        setHandler();
        runTicks("P");
        exit(0);
    }
}

在没有valgrind的情况下首先运行它们,并比较两个程序的退出代码。然后在瓦尔格林德下运行它们并享受。

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

最新更新