Browse files

Stream stdin out

  • Loading branch information...
1 parent ee1b5b0 commit 11541662591757a6a7d3b8ab91e7b12c2ef6949b @felixge felixge committed with piscisaureus Sep 14, 2011
Showing with 67 additions and 10 deletions.
  1. +1 −0 include/uv.h
  2. +31 −10 src/unix/process.c
  3. +12 −0 test/run-tests.c
  4. +2 −0 test/test-list.h
  5. +21 −0 test/test-spawn-sync.c
View
1 include/uv.h
@@ -886,6 +886,7 @@ typedef struct uv_spawn_sync_t{
int combine;
char *stdin_buf;
+ int stdin_written;
int stdin_size;
char *stdout_buf;
View
41 src/unix/process.c
@@ -320,7 +320,8 @@ int uv_spawn_sync(uv_loop_t* loop, uv_spawn_sync_t* spawn) {
int64_t start_time;
struct sigaction siga;
static sigset_t sigset;
- fd_set pipes;
+ fd_set read_fds;
+ fd_set write_fds;
struct timeval select_timeout;
@@ -397,8 +398,8 @@ int uv_spawn_sync(uv_loop_t* loop, uv_spawn_sync_t* spawn) {
}
if (spawn->stdin_buf) {
- int c = write(stdin_pipe[1], spawn->stdin_buf, spawn->stdin_size);
close(stdin_pipe[0]); /* close the read end */
+ nfds = MAX(nfds, stdin_pipe[1]);
}
nfds = nfds + 1;
@@ -419,25 +420,34 @@ int uv_spawn_sync(uv_loop_t* loop, uv_spawn_sync_t* spawn) {
int64_t time_to_timeout;
int r;
- FD_ZERO(&pipes);
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
if (spawn->stdout_buf) {
- FD_SET(stdout_pipe[0], &pipes);
+ FD_SET(stdout_pipe[0], &read_fds);
}
if (spawn->stderr_buf) {
- FD_SET(stderr_pipe[0], &pipes);
+ FD_SET(stderr_pipe[0], &read_fds);
}
- FD_SET(sigchld_pipe[0], &pipes);
+ if (spawn->stdin_buf) {
+ FD_SET(stdin_pipe[1], &write_fds);
+ }
+
+ FD_SET(sigchld_pipe[0], &read_fds);
elapsed = uv_now(loop) - start_time;
time_to_timeout = spawn->timeout - elapsed;
+ if (time_to_timeout < 0) {
+ /* TODO: is this the right thing todo, or does this mean we timed out? */
+ time_to_timeout = 0;
+ }
select_timeout.tv_sec = time_to_timeout / 1000;
select_timeout.tv_usec = time_to_timeout % 1000;
- r = select(nfds, &pipes, NULL, NULL, &select_timeout);
+ r = select(nfds, &read_fds, &write_fds, NULL, &select_timeout);
if (r == -1) {
if (errno == EINTR) {
@@ -470,7 +480,18 @@ int uv_spawn_sync(uv_loop_t* loop, uv_spawn_sync_t* spawn) {
return 0;
}
- if (spawn->stdout_buf && FD_ISSET(stdout_pipe[0], &pipes)) {
+ if (spawn->stdin_buf && FD_ISSET(stdin_pipe[1], &write_fds) && spawn->stdin_written < spawn->stdin_size) {
+ int written = write(stdin_pipe[1], spawn->stdin_buf + spawn->stdin_written, spawn->stdin_size - spawn->stdin_written);
+
+ if (written == -1 && errno != EINTR) {
+ uv_err_new(loop, errno);
+ goto error;
+ } else {
+ spawn->stdin_written += written;
+ }
+ }
+
+ if (spawn->stdout_buf && FD_ISSET(stdout_pipe[0], &read_fds)) {
if (spawn->stdout_size - spawn->stdout_read <= 0) {
/* Check for buffer overflow. */
uv_err_new_artificial(loop, UV_ENOBUFS);
@@ -488,7 +509,7 @@ int uv_spawn_sync(uv_loop_t* loop, uv_spawn_sync_t* spawn) {
spawn->stdout_read += r;
}
- if (spawn->stderr_buf && FD_ISSET(stderr_pipe[0], &pipes)) {
+ if (spawn->stderr_buf && FD_ISSET(stderr_pipe[0], &read_fds)) {
if (spawn->stderr_size - spawn->stderr_read <= 0) {
/* Check for buffer overflow. */
uv_err_new_artificial(loop, UV_ENOBUFS);
@@ -504,7 +525,7 @@ int uv_spawn_sync(uv_loop_t* loop, uv_spawn_sync_t* spawn) {
spawn->stderr_read += r;
}
- if (FD_ISSET(sigchld_pipe[0], &pipes)) {
+ if (FD_ISSET(sigchld_pipe[0], &read_fds)) {
/* The child process has exited. */
int status;
View
12 test/run-tests.c
@@ -71,6 +71,18 @@ static int maybe_run_test(int argc, char **argv) {
return 1;
}
+ if (strcmp(argv[1], "spawn_helper_stdin_stream") == 0) {
+ char buffer[4];
+ fgets(buffer, sizeof(buffer), stdin);
+ fputs(buffer, stdout);
+
+ uv_sleep(1000);
+
+ fgets(buffer, sizeof(buffer), stdin);
+ fputs(buffer, stdout);
+ return 1;
+ }
+
if (strcmp(argv[1], "spawn_helper_timeout") == 0) {
/* Never surrender, never return! */
while (1) uv_sleep(10000);
View
2 test/test-list.h
@@ -88,6 +88,7 @@ TEST_DECLARE (spawn_sync_stdout_overflow)
TEST_DECLARE (spawn_sync_stderr_overflow)
TEST_DECLARE (spawn_sync_combine_stdio)
TEST_DECLARE (spawn_sync_stdin)
+TEST_DECLARE (spawn_sync_stdin_stream)
TEST_DECLARE (spawn_sync_timeout)
TEST_DECLARE (fs_file_noent)
TEST_DECLARE (fs_file_async)
@@ -220,6 +221,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_sync_stderr_overflow)
TEST_ENTRY (spawn_sync_combine_stdio)
TEST_ENTRY (spawn_sync_stdin)
+ TEST_ENTRY (spawn_sync_stdin_stream)
TEST_ENTRY (spawn_sync_timeout)
#ifdef _WIN32
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
View
21 test/test-spawn-sync.c
@@ -60,12 +60,14 @@ void debug(int r) {
fprintf(stderr, "spawn.stderr_read: %i\n", spawn.stderr_read);
fprintf(stderr, "spawn.stderr_size: %i\n", spawn.stderr_size);
fprintf(stderr, "spawn.stderr: %s\n", spawn.stderr_buf);
+ fprintf(stderr, "spawn.stdin_written: %i\n", spawn.stdin_written);
fprintf(stderr, "spawn.exit_timeout: %i\n", spawn.exit_timeout);
fprintf(stderr, "spawn.exit_code: %i\n", spawn.exit_code);
fprintf(stderr, "spawn.exit_signal: %i\n", spawn.exit_signal);
uv_err_t err = uv_last_error(uv_default_loop());
fprintf(stderr, "uv_last_error_name: %s\n", uv_err_name(err));
+ fprintf(stderr, "uv_strerror: %s\n", uv_strerror(err));
fprintf(stderr, "----------------------------------------\n");
}
@@ -237,6 +239,25 @@ TEST_IMPL(spawn_sync_stdin) {
return 0;
}
+TEST_IMPL(spawn_sync_stdin_stream) {
+ int r;
+ uv_init();
+
+ init_process_options("spawn_helper_stdin_stream");
+
+ spawn.stdin_buf = "stdin\n";
+ spawn.stdin_size = strlen(spawn.stdin_buf);
+
+ r = uv_spawn_sync(uv_default_loop(), &spawn);
+ debug(r);
+
+ ASSERT(r == 0);
+ ASSERT(strcmp(spawn.stdout_buf, spawn.stdin_buf) == 0);
+ ASSERT(spawn.stdout_read == strlen(spawn.stdin_buf));
+
+ return 0;
+}
+
TEST_IMPL(spawn_sync_timeout) {
int r;
uv_init();

0 comments on commit 1154166

Please sign in to comment.