0

我遇到了 dup2() 和 pipe() 的问题。

当我尝试将管道的写入端复制到 STDOUT_FILENO 时,我收到了 EBADF。

我中断dup2(pout[1], STDOUT_FILENO)了 gdb 并检查了/proc/$pid/fdinfo/$pout[1]是否有 O_WRONLY 标志。这个麻烦快把我逼疯了。

笔记:

  • 在函数开始时,我将所有管道初始化为-1。
  • 这个问题只发生在 x86 上,在我的 x86_64 工作站上一切正常。
  • 操作系统是 Gentoo GNU/Linux(x86 和 x86_64 机器)
if(pipe2(pexec, O_CLOEXEC)) {
  fprintf(stderr, "%s: exec pipe: %s\n", __func__, strerror(errno));
  goto start_fail;
}

if(h->have_stdin && pipe(pin)) {
  fprintf(stderr, "%s: input pipe: %s\n", __func__, strerror(errno));
  goto start_fail;
}

if(h->have_stdout && pipe(pout)) {
  fprintf(stderr, "%s: output pipe: %s\n", __func__, strerror(errno));
  goto start_fail;
}

if(h->have_stdout) {
  printf("%s: output pipes: rd=%d wr=%d\n", __func__, pout[0], pout[1]);
}

if((pid = fork()) < 0) {
  fprintf(stderr, "%s: fork: %s\n", __func__, strerror(errno));
  goto start_fail;
} else if(!pid) {
  // child
  close(pexec[0]);
  close(pin[1]);
  close(pout[0]);

  i= open("/dev/null", O_RDWR);

  if(pin[0] == -1)
    pin[0] = i;
  if(pout[1] == -1)
    pout[1] = i;

  if(h->workdir)
    chdir(h->workdir);

  if(dup2(pin[0], STDIN_FILENO)) {
    fprintf(stderr, "%s: dup2(%d, %d): %s\n", __func__, pin[0], STDIN_FILENO, strerror(errno));
  }
  if(dup2(pout[1], STDOUT_FILENO)) {
    fprintf(stderr, "%s: dup2(%d, %d): %s\n", __func__, pout[1], STDOUT_FILENO, strerror(errno));
  }
#ifdef NDEBUG
  dup2(i, STDERR_FILENO);
#endif

  close(i);
  close(pin[0]);
  close(pout[1]);

  execv(argv[0], argv);
  fprintf(stderr, "%s: execv: %s\n", __func__, strerror(errno));
  write(pexec[1], "!", 1);
  close(pexec[1]);
  exit(-1);
} else {
  // parent
  close(pexec[1]);
  close(pin[0]);
  close(pout[1]);
  if(read(pexec[0],&exec_failed, 1)) {
    fprintf(stderr, "%s: exec failed\n", __func__);
    waitpid(pid, NULL, 0);
    goto start_fail;
  }
#ifndef NDEBUG
  printf("%s: successfully started command '%s' (pid=%d)\n", __func__, argv[0], pid);
#endif
  close(pexec[0]);
}

输出如下:

...
handle_cmd_start: output pipes: rd=12 wr=13
...
...
handle_cmd_start: dup2(13, 1): Bad file descriptor
handle_cmd_start: successfully started command 'tools/nmap/nmap' (pid=1154)
....

提前感谢您的帮助。

4

1 回答 1

4

dup2成功时返回目标文件描述符,而不是零。您的支票不应该是if (dup2(...))but if (dup2(...) < 0)

于 2014-09-08T12:53:05.460 回答