【问题标题】:Disappearing child process消失的子进程
【发布时间】:2014-10-06 02:11:29
【问题描述】:

我有这个方法:

int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc) {
    std::cout << "Building Pipe...\ncmd1: " << cmd1 << "\n cmd2: " << cmd2 << "\n";
    int *pipefd = new int[2];
    if (pipe(pipefd) < 0) {
        std::cerr << "There was an error setting up the pipe.\n";
        return -1;
    }
    pid_t cpid1 = fork();
    std::cout << "First process forked, cpid: " << cpid1 << " - Process " << getpid() << "\n";
    switch (cpid1) {
        case -1:
            std::cerr << "There was an error forking the process.\n";
            return -1;
            break;
        case 0: // this is the part that isn't executing
            std::cout << "Dup2 return: " << dup2(pipefd[1], 1) << "\n";
            std::cout << "Process " << getpid() << " duped and about to exec.\n";
            execvp(cmd1.c_str(), argv1);
            std::cout << "Process " << getpid() << " about to exit.\n";
            _exit(0);
            break;
        default:
            pid_t cpid2 = fork();
            switch (cpid2) {
                case -1:
                    std::cerr << "There was an error forking the process.\n";
                    return -1;
                    break;
                case 0:
                    dup2(pipefd[0], 0);
                    std::cout << "Process " << getpid() << " duped and about to exec.\n";
                    execvp(cmd2.c_str(), argv2);
                    _exit(0);
                    break;
                default:
                    if (conc) {

                    } else {
                        int status1, status2;
                        std::cout << "Process " << getpid() << " about to wait.\n";
                        waitpid(cpid1, &status1, 0);
                        waitpid(cpid2, &status2, 0);
                    }
                    break;
            }
        }
    delete[] pipefd;
    return 0;
}

我添加打印语句只是为了调试。然而,当这个方法运行时,这就是被打印的内容。

Building Pipe...
cmd1: cat
cmd2: wc
First process forked, cpid: 1454 - Process 1453
First process forked, cpid: 0 - Process 1454
Process 1453 about to wait.
Process 1455 duped and about to exec.

进程 1454 是第一个分叉的进程,它在创建后立即打印消息。但是,它从不打印来自 switch 语句的任何消息,并且从不执​​行指定的程序(在本例中为 cat)。该进程不会像僵尸一样徘徊,它只是消失了。结果,第二个子进程挂起并且实际上没有做任何事情。

(另外,补充一下,我知道我还没有添加所有适当的错误处理,功能还没有完成)。

【问题讨论】:

  • int *pipefd = new int[2]; 真的吗?
  • 你能给我们一个minimal complete example吗?我们不知道您传递的所有参数,我怀疑所有这些代码对于重现问题是必要的。

标签: c++ exec fork pipe dup2


【解决方案1】:

您看不到来自 switch 语句的消息,因为它们已被写入管道。尝试将std::cout 替换为std::cerr

【讨论】:

  • 每天提醒我我是个白痴。谢谢你。现在问题变成了我在管道方面做错了什么。
  • @NickDell'osa:答案在jaba10answer
【解决方案2】:

管道在检测到 EOF 时结束,为此,您必须在复制后关闭不需要的描述符(在子级和父级中):

close(pipefd[0]);
close(pipefd[1]);

另外,一定要检查execvp的返回值,你可能在argv中有错误:

if (execvp(cmd1.c_str(), argv1) == -1) {
    // check errno here
}

另外,请务必以 nullptr 作为最后一个元素来结束 argv,并且 argv[0] 必须是命令本身。原型:

int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc)

...让我觉得你没有提供第一个元素 (argv[0] = cmd1)。如果你在 argv 中有这个额外的值 (cmdX) 来运行 build_pipe_and_call,你就不需要它了。

请记住,如果 execvp 运行良好,您将永远无法访问程序中的后续代码,因此您将不会看到预期的某些消息:

execvp(cmd1.c_str(), argv1);
std::cout << "Process " << getpid() << " about to exit.\n"; // if execvp didn't fail, it's never reached

一旦你重复使用 std::cout,也要小心,如@larpico answered

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 2016-08-25
    • 1970-01-01
    • 2016-06-08
    相关资源
    最近更新 更多