This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

When the parent's stdio FDs are passed to a child, make them temporar…

…ily blocking.

Many programs do not handle non-blocking stdio very well.  In particular,
man and less have serious problems with this, and since stdout isn't being
flushed after each write, the output jumps about on the screen as you page
down.  Programs that do use non-blocking stdio will set that flag themselves
(as node does).

This puts the stdio file descriptors into blocking mode before sharing them
with the child process, so that one could spawn a vim subprocess, or some
other program that depends on blocking IO.
  • Loading branch information...
isaacs authored and ry committed Aug 3, 2010
1 parent a6bc68a commit e9aacd40c68e33bfeef24a396d63e42ccbb3b054
Showing with 14 additions and 6 deletions.
  1. +14 −6 src/node_child_process.cc
View
@@ -34,6 +34,14 @@ static inline int SetNonBlocking(int fd) {
}
+static inline int SetBlocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ int r = fcntl(fd, F_SETFL, flags ^ O_NONBLOCK);
+ if (r != 0) perror("SetBlocking()");
+ return r;
+}
+
+
void ChildProcess::Initialize(Handle<Object> target) {
HandleScope scope;
@@ -222,24 +230,24 @@ int ChildProcess::Spawn(const char *file,
if (custom_fds[0] == -1) {
close(stdin_pipe[1]); // close write end
dup2(stdin_pipe[0], STDIN_FILENO);
- }
- else {
+ } else {
+ SetBlocking(custom_fds[0]);
dup2(custom_fds[0], STDIN_FILENO);
}
if (custom_fds[1] == -1) {
close(stdout_pipe[0]); // close read end
dup2(stdout_pipe[1], STDOUT_FILENO);
- }
- else {
+ } else {
+ SetBlocking(custom_fds[1]);
dup2(custom_fds[1], STDOUT_FILENO);
}
if (custom_fds[2] == -1) {
close(stderr_pipe[0]); // close read end
dup2(stderr_pipe[1], STDERR_FILENO);
- }
- else {
+ } else {
+ SetBlocking(custom_fds[2]);
dup2(custom_fds[2], STDERR_FILENO);
}

0 comments on commit e9aacd4

Please sign in to comment.