C 捕获父级中的子级错误

C 捕获父级中的子级错误,c,exec,fork,C,Exec,Fork,我正在尝试编写以下C赋值:一个程序如果接受两个参数,将运行第一个参数,然后在成功时运行第二个参数。 以下是我的想法: #include <stdio.h> #include <unistd.h> #include <assert.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> char ** split(char * s) { char

我正在尝试编写以下C赋值:一个程序如果接受两个参数,将运行第一个参数,然后在成功时运行第二个参数。 以下是我的想法:

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

char ** split(char * s) {
  char ** words = malloc(sizeof(char *));
  int i = 0;
  char * word = strtok(strdup(s), " ");
  while (word) {
    words = realloc(words, sizeof(char *) * (i + 1));
    words[i] = malloc(strlen(word) + 1);
    strcpy(words[i++], word);
    word = strtok(NULL, " ");
  }
  words[i] = NULL;
  return words;
}


int main(int argc, char * argv[]) {
  char ** argv1 = split(argv[1]);
  char ** argv2 = split(argv[2]);

  int t = fork();
  if (t == -1)
    exit(1);
  else if (t == 0) 
    execvp(argv1[0], argv1);
  else {
    int status;
    wait(&status);
    if (WIFEXITED(status))
      printf("exit status %d\n", WEXITSTATUS(status));
  }
  return 0;
}
我尝试了WSIGNALED,WSTOPPED,但我真的不知道如何捕捉错误。我的搜索方向是正确的,还是完全不同的,例如启动一个shell,然后执行我的命令,错误是shell固有的,而不是命令本身的?

您应该检查wait是否真的返回了什么。如果返回值不是您的childpid,则无法解释状态

    if(wait(&status) != child)
    {
        printf("Error in wait\n");
        return -1;
    }
我使用这段代码来解释各种状态。我认为通过我使用的日志注释,代码很容易理解

如果您的孩子崩溃了,它将被一个信号而不是退出,在这种情况下,您还必须检查相应的宏

    if(WIFEXITED(status) == 0 && WIFSIGNALED(status) == 0)
    {
        LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " still running";
        setRunning(true);
        setTerminated(false);
        setTerminationSignal(0);
        setExitStatus(-1);
    }
    else if(WIFSTOPPED(status))
    {
        LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " stopped";
        setRunning(false);
    }
    else if(WIFCONTINUED(status))
    {
        LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " continued";
        setRunning(true);
    }
    else
    {
        setRunning(false);
        setTerminated(true);
        if(WIFEXITED(status))
        {
            LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " terminated normally";
            setTerminationSignal(0);
            setExitStatus(WEXITSTATUS(status));   // Exitcode from the child
        }
        else
        {
            LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " terminated by signal";
            setTerminationSignal(WTERMSIG(status));
            setExitStatus(-1);
        }
    }
将您的呼叫更改为execvp。尝试:


非常感谢大家的意见。我只需要返回execv的潜在返回,然后它就成为原始fork等待的WEXITSTATUS

else if (t == 0) 
**return** execvp(argv1[0], argv1);

检查您的返回值。execvp成功了吗,还是返回了?并打开编译器警告。我使用gcc-Wall。我能做得更多吗?令人费解的是,无论我尝试像if-ls或if-toto-toto这样的东西,execvp都不会回来。如果你包括在内,你应该得到一个关于-Wall的警告。迷惑不同于调用未指定的行为。argv[1]是第二个参数的错误类型。我的错误是,程序实际上稍微复杂一些,我希望简化它以解决这个问题,但是execvp调用是正确的。我将更新问题以反映这一点。只有在无法启动execvp时才会返回。这就是你的意思吗?如果命令失败,返回一个错误?正如我明确指出的,这是一个作业,这意味着我是一个初学者。所以我并不假装理解,但现在程序工作了-例如:我的if ToToTo echo success和我的if ls fakestring echo success不响应成功,而:我的if ls-l echo success。不,你的程序不工作。execvp仅在出现错误时返回。你根本没有给外部程序打电话。我为我的粗鲁道歉,但它确实有效。评论中的三个例子正是它们应该做的。除了我在原始帖子中忘记更正的第二部分:ifWEXITSTATUSstatus==0 execvpargv2[0],argv2;返回execvp。。。是错误的,除非您的意图是在未成功执行外部程序时未能注意到。巧合的是,在这种情况下,您返回了一个错误,但应该发出一条错误消息。你是一个公认的初学者,所以试着听听我们中那些不是的人的意见。如果提交作业时返回execvp…,则表示您不了解execvp的工作原理。它不会返回外部程序的退出状态。
execvp( argv[1], argv + 1 );
else if (t == 0) 
**return** execvp(argv1[0], argv1);