diff --git a/src/unix/process.c b/src/unix/process.c index 8896726e..18d056e9 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -367,6 +367,7 @@ int uv_spawn(uv_loop_t* loop, int err; int exec_errorno; int i; + int status; assert(options->file != NULL); assert(!(options->flags & ~(UV_PROCESS_DETACHED | @@ -453,11 +454,17 @@ int uv_spawn(uv_loop_t* loop, if (r == 0) ; /* okay, EOF */ - else if (r == sizeof(exec_errorno)) - ; /* okay, read errorno */ - else if (r == -1 && errno == EPIPE) - ; /* okay, got EPIPE */ - else + else if (r == sizeof(exec_errorno)) { + do + err = waitpid(pid, &status, 0); /* okay, read errorno */ + while (err == -1 && errno == EINTR); + assert(err == pid); + } else if (r == -1 && errno == EPIPE) { + do + err = waitpid(pid, &status, 0); /* okay, got EPIPE */ + while (err == -1 && errno == EINTR); + assert(err == pid); + } else abort(); uv__close(signal_pipe[0]); diff --git a/test/test-list.h b/test/test-list.h index a021319f..4fc97c1b 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -196,6 +196,9 @@ TEST_DECLARE (fail_always) TEST_DECLARE (pass_always) TEST_DECLARE (socket_buffer_size) TEST_DECLARE (spawn_fails) +#ifndef _WIN32 +TEST_DECLARE (spawn_fails_check_for_waitpid_cleanup) +#endif TEST_DECLARE (spawn_exit_code) TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) @@ -553,6 +556,9 @@ TASK_LIST_START TEST_ENTRY (socket_buffer_size) TEST_ENTRY (spawn_fails) +#ifndef _WIN32 + TEST_ENTRY (spawn_fails_check_for_waitpid_cleanup) +#endif TEST_ENTRY (spawn_exit_code) TEST_ENTRY (spawn_stdout) TEST_ENTRY (spawn_stdin) diff --git a/test/test-spawn.c b/test/test-spawn.c index 9b003002..6807a6d3 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -21,6 +21,7 @@ #include "uv.h" #include "task.h" +#include #include #include #include @@ -34,6 +35,7 @@ # include #else # include +# include #endif @@ -180,6 +182,37 @@ TEST_IMPL(spawn_fails) { } +#ifndef _WIN32 +TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) { + int r; + int status; + int err; + + init_process_options("", fail_cb); + options.file = options.args[0] = "program-that-had-better-not-exist"; + + r = uv_spawn(uv_default_loop(), &process, &options); + ASSERT(r == UV_ENOENT || r == UV_EACCES); + ASSERT(0 == uv_is_active((uv_handle_t*) &process)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + /* verify the child is successfully cleaned up within libuv */ + do + err = waitpid(process.pid, &status, 0); + while (err == -1 && errno == EINTR); + + ASSERT(err == -1); + ASSERT(errno == ECHILD); + + uv_close((uv_handle_t*) &process, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif + + TEST_IMPL(spawn_exit_code) { int r;