替换并通过 ssh 打开 stdin/stdout

发布于 2024-11-27 22:38:00 字数 1019 浏览 1 评论 0原文

我正在开发一个使用标准输入和标准输出管道与子进程通信的系统。子进程使用 api 库来促进这种通信,我需要为该库编写单元测试。我能弄清楚如何正确测试这些函数的唯一方法是用管道替换 stdin/stdout ,以便测试在调用函数时可以假装是父系统。

/* replace stdin and stdout with pipes */
void setup(void) {
  pipe(in_sub);
  pipe(out_sub);

  dup2(out_sub[1], fileno(stdout));
  dup2( in_sub[0],  fileno(stdin));
  read_from = fdopen(out_sub[0], "rb");
  write_to  = fdopen( in_sub[1], "wb");

  stdout_t = fopen("/dev/tty", "wb");
  stdin_t  = fopen("/dev/tty", "rb");
}

/* reopen stdin and stdout for future test suites */
void teardown(void) {
  fclose(read_from);
  fclose(write_to);

  stdout = stdout_t;
  stdin  = stdin_t;

  close(in_sub[0]);
  close(in_sub[1]);
  close(out_sub[0]);
  close(out_sub[1]);
}

我尝试过将 stdin 和 stdout 保存在 temps 中,并在它们上使用 fdopen() (应该可以工作,因为它们是 FILE*),但这不会导致内容被正确写入管道。当直接从主机的 shell 运行时,该代码确实可以完美运行。通过 ssh 运行时会出现此问题。单元测试执行得很好,但是当我在这个测试套件之后向标准输出写入任何内容时,我收到了损坏的管道错误。

我该怎么做才能避免使用 dup2 以便 stdin 和 stdout 永远不会关闭,或者如何重新打开 stdin 和 stdout 以便它们能够在 shell 中和通过 ssh 正确工作?

I'm working on a system that communicates with child processes using pipes to stdin and stdout. The child processes use a api library to facilitate this communication and I need to write unit tests for the library. The only way that I could figure out how to properly test these functions is to replace stdin/stdout with pipes so that the tests can pretend to be the parent system when calling the functions.

/* replace stdin and stdout with pipes */
void setup(void) {
  pipe(in_sub);
  pipe(out_sub);

  dup2(out_sub[1], fileno(stdout));
  dup2( in_sub[0],  fileno(stdin));
  read_from = fdopen(out_sub[0], "rb");
  write_to  = fdopen( in_sub[1], "wb");

  stdout_t = fopen("/dev/tty", "wb");
  stdin_t  = fopen("/dev/tty", "rb");
}

/* reopen stdin and stdout for future test suites */
void teardown(void) {
  fclose(read_from);
  fclose(write_to);

  stdout = stdout_t;
  stdin  = stdin_t;

  close(in_sub[0]);
  close(in_sub[1]);
  close(out_sub[0]);
  close(out_sub[1]);
}

I have tried just saving stdin and stdout in temps and using fdopen() on them (should work because they are FILE*) but this doesn't result in things being correctly written to the pipe. This code does work perfectly when being run directly from the host's shell. The problem occurs when running over ssh. The unit tests execute perfectly, but when I go to write anything to stdout after this test suite, I receive a broken pipe error.

What can I do that avoids using the dup2 so that stdin and stdout never get closed, or how can I reopen stdin and stdout such that they will correctly work in the shell and over ssh?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玻璃人 2024-12-04 22:38:01

stdin、stdout 只是 FILE* 指向一个结构体(对象),该结构体内部的 fd 设置为 0(和 1)。因此,当您执行 dup2 时,文件 0 和 1 不再起作用。您需要做的是在执行 dup2 之前从头开始创建一个新的文件对象,因此这可能就是您需要的所有修改;

void setup(void) {
  int dupin, dupout;

  dupin = dup(0);  // Create an extra fd to stdin
  dupout = dup(1);  // create an extra fd to stdout

  pipe(in_sub);
  pipe(out_sub);

  dup2(out_sub[1], fileno(stdout));
  dup2( in_sub[0],  fileno(stdin));
  read_from = fdopen(out_sub[0], "rb");
  write_to  = fdopen( in_sub[1], "wb");

  stdout_t = fdopen(dupout, "wb");
  stdin_t  = fdopen(dupin, "rb");
}

The stdin, stdout is just FILE* pointing to a struct (object) which internally have their fd set to 0 (and 1). Hence when you do the dup2, the file 0 and 1 no longer work. What you need to do is to create a new file object from scratch before doing the dup2, so this may be all the modification you need;

void setup(void) {
  int dupin, dupout;

  dupin = dup(0);  // Create an extra fd to stdin
  dupout = dup(1);  // create an extra fd to stdout

  pipe(in_sub);
  pipe(out_sub);

  dup2(out_sub[1], fileno(stdout));
  dup2( in_sub[0],  fileno(stdin));
  read_from = fdopen(out_sub[0], "rb");
  write_to  = fdopen( in_sub[1], "wb");

  stdout_t = fdopen(dupout, "wb");
  stdin_t  = fdopen(dupin, "rb");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文