c++ - 使用 socketpair : hangs reading output from child process 进行双向通信

标签 c++ linux sockets ipc

我正在尝试使用套接字对让父进程向执行不同程序(例如 grep)的子进程提供输入,然后读取结果输出。该程序卡在 while 循环中,该循环读取子程序执行的程序的输出。子级将 stdin 和 stdout 复制到套接字对的末端,父级和子级都关闭了对的未使用端。

有趣的是,如果 child 执行我编写的程序(好吧,我从 Stevens Advanced Programming in the Unix Env​​ironment 中抄袭了它)一切都按预期运行。但是,如果子进程执行 grep(或其他一些标准程序),父进程总是会挂起以尝试读取输出。我无法确定输入是否未到达 grep,或者 grep 是否无法确定输入的结尾,或者输出是否以某种方式丢失。

代码如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <cstdio>
#include <cerrno>
#include <iostream>
using namespace std;

void 
sigpipe_handler(int sig, siginfo_t *siginfo, void * context) {
  cout << "caught SIGPIPE\n";
  pid_t pid;

  if (errno == EPIPE) {
    throw "SIGPIPE caught";
  }
}

int main(int argc, char** argv) {

  struct sigaction sa;
  memset(&sa, '\0', sizeof(struct sigaction));
  sa.sa_sigaction = sigpipe_handler;
  sa.sa_flags = SA_SIGINFO | SA_RESTART;
  sigaction(SIGPIPE, &sa, NULL);

  int sp[2];
  socketpair(PF_UNIX, SOCK_STREAM, AF_UNIX, sp);

  pid_t childPid = fork();

  if (childPid == 0) {
    close(sp[0]);
    if (dup2(sp[1], STDIN_FILENO) != STDIN_FILENO) throw "dup2 error to stdin";
    if (dup2(sp[1], STDOUT_FILENO) != STDOUT_FILENO) throw "dup2 error to stdout";

    execl("/bin/grep", "grep", "-n", "namespace", (char*)NULL);
  } else {
    close(sp[1]);
    char line[80];
    int n;
    try {
      while (fgets(line, 80, stdin) != NULL) {
 n = strlen(line);
 if (write(sp[0], line, n) != n) {
   throw "write error to pipe";
 }

 if ((n=read(sp[0], line, 80)) < 0) {  // hangs here
   throw "read error from pipe";
 }
 if (n ==0) {
   throw "child closed pipe";
   break;
 }
 line[n] = 0;
 if (fputs(line, stdout) == EOF) {
   throw "puts error";
 }
 if (ferror(stdin)) {
   throw "fgets error on stdin";
 }
 exit(0);
      }
    } catch (const char* e) {
      cout << e << endl;
    }

    int status;
    waitpid(childPid, &status, 0);
  }
}

最佳答案

您的代码挂起,因为 grep 的输出可能少于 80 个字节,并且您正在对 sp[0] 发出阻塞读取。这样做的正确方法是将两个套接字标记为非阻塞并在它们上选择()。

您还忘记了在 wait() 之前关闭 (sp[0]),这将使您的子进程等待输入。

关于c++ - 使用 socketpair : hangs reading output from child process 进行双向通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3585517/

相关文章:

C++ 编译的应用程序

javascript - 为需要的 Node 模块创建工厂

sockets - 为什么在此网络服务器示例中需要额外的\r\n?

c++ - 魔鬼不加载图像与 linux 构建

C++ WinSock 错误 10053

c++ - 如何计算 ELF 文件中的静态初始值设定项?

c# - 从 TCP 套接字接收确认

sockets - 如何将 UDP 消息发送到环回地址,然后从中读取?

c++ - QNetwork回复: Network access is disabled in QWebView

linux - ./script.sh 和 bash script.sh 有什么区别