Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

spawn doesn't allow parent fd to be inherited by multiple child fds #763

Closed
malern opened this issue Apr 5, 2013 · 2 comments
Closed

spawn doesn't allow parent fd to be inherited by multiple child fds #763

malern opened this issue Apr 5, 2013 · 2 comments

Comments

@malern
Copy link

malern commented Apr 5, 2013

I'm trying to spawn a child process whose stdout and stderr are both redirected to the same file. I'm opening the file in the parent process and assigning the same fd to both options.stdio[1].data.fd and options.stdio[2].data.fd. The child process executes correctly, but only stdout ends up going to the file.

I believe the problem is because the original fd is being closed immediately after being duplicated in uv__process_child_init. So stdout is duplicated correctly, but when it loops back round to do the same for stderr the fd is no longer valid.

libuv/src/unix/process.c

Lines 311 to 312 in 0635e29

dup2(use_fd, fd);
close(use_fd);

I modified one of the existing tests to illustrate the problem

TEST_IMPL(spawn_output_to_file) {
  int r;
  uv_file file;
  uv_fs_t fs_req;
  uv_stdio_container_t stdio[2];

  /* Setup. */
  unlink("output_file");

  init_process_options("spawn_helper6", exit_cb);

  r = uv_fs_open(uv_default_loop(), &fs_req, "output_file", O_CREAT | O_RDWR,
      S_IREAD | S_IWRITE, NULL);
  ASSERT(r != -1);
  uv_fs_req_cleanup(&fs_req);

  file = r;

  options.stdio = stdio;
  options.stdio[0].flags = UV_IGNORE;
  options.stdio[1].flags = UV_INHERIT_FD;
  options.stdio[1].data.fd = file;
  options.stdio[2].flags = UV_INHERIT_FD;
  options.stdio[2].data.fd = file;
  options.stdio_count = 3;

  r = uv_spawn(uv_default_loop(), &process, options);
  ASSERT(r == 0);

  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  ASSERT(r == 0);

  ASSERT(exit_cb_called == 1);
  ASSERT(close_cb_called == 1);

  r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
      0, NULL);
  ASSERT(r == 27);
  uv_fs_req_cleanup(&fs_req);

  r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
  ASSERT(r == 0);
  uv_fs_req_cleanup(&fs_req);

  printf("output is: %s", output);
  ASSERT(strcmp("hello world\nhello errworld\n", output) == 0);

  /* Cleanup. */
  unlink("output_file");

  MAKE_VALGRIND_HAPPY();
  return 0;
}
@piscisaureus
Copy link

@bnoordhuis I think you should take a look :)

@bnoordhuis
Copy link
Contributor

Sorry, must've missed this one. Thanks for the bug report, continues in #923.

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants