unix: reap child on execvp() failure
Reap the forked process when execvp() fails. Fixes leaking zombie child processes. PR-URL: https://github.com/libuv/libuv/pull/274 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
252f3624c2
commit
3616e61439
@ -367,6 +367,7 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
int err;
|
int err;
|
||||||
int exec_errorno;
|
int exec_errorno;
|
||||||
int i;
|
int i;
|
||||||
|
int status;
|
||||||
|
|
||||||
assert(options->file != NULL);
|
assert(options->file != NULL);
|
||||||
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
|
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
|
||||||
@ -453,11 +454,17 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
|
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
; /* okay, EOF */
|
; /* okay, EOF */
|
||||||
else if (r == sizeof(exec_errorno))
|
else if (r == sizeof(exec_errorno)) {
|
||||||
; /* okay, read errorno */
|
do
|
||||||
else if (r == -1 && errno == EPIPE)
|
err = waitpid(pid, &status, 0); /* okay, read errorno */
|
||||||
; /* okay, got EPIPE */
|
while (err == -1 && errno == EINTR);
|
||||||
else
|
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();
|
abort();
|
||||||
|
|
||||||
uv__close(signal_pipe[0]);
|
uv__close(signal_pipe[0]);
|
||||||
|
|||||||
@ -196,6 +196,9 @@ TEST_DECLARE (fail_always)
|
|||||||
TEST_DECLARE (pass_always)
|
TEST_DECLARE (pass_always)
|
||||||
TEST_DECLARE (socket_buffer_size)
|
TEST_DECLARE (socket_buffer_size)
|
||||||
TEST_DECLARE (spawn_fails)
|
TEST_DECLARE (spawn_fails)
|
||||||
|
#ifndef _WIN32
|
||||||
|
TEST_DECLARE (spawn_fails_check_for_waitpid_cleanup)
|
||||||
|
#endif
|
||||||
TEST_DECLARE (spawn_exit_code)
|
TEST_DECLARE (spawn_exit_code)
|
||||||
TEST_DECLARE (spawn_stdout)
|
TEST_DECLARE (spawn_stdout)
|
||||||
TEST_DECLARE (spawn_stdin)
|
TEST_DECLARE (spawn_stdin)
|
||||||
@ -553,6 +556,9 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY (socket_buffer_size)
|
TEST_ENTRY (socket_buffer_size)
|
||||||
|
|
||||||
TEST_ENTRY (spawn_fails)
|
TEST_ENTRY (spawn_fails)
|
||||||
|
#ifndef _WIN32
|
||||||
|
TEST_ENTRY (spawn_fails_check_for_waitpid_cleanup)
|
||||||
|
#endif
|
||||||
TEST_ENTRY (spawn_exit_code)
|
TEST_ENTRY (spawn_exit_code)
|
||||||
TEST_ENTRY (spawn_stdout)
|
TEST_ENTRY (spawn_stdout)
|
||||||
TEST_ENTRY (spawn_stdin)
|
TEST_ENTRY (spawn_stdin)
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -34,6 +35,7 @@
|
|||||||
# include <wchar.h>
|
# include <wchar.h>
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
# include <sys/wait.h>
|
||||||
#endif
|
#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) {
|
TEST_IMPL(spawn_exit_code) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user