diff --git a/include/uv.h b/include/uv.h index c6b68919..4af154e9 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1063,12 +1063,6 @@ typedef struct uv_process_options_s { */ char* cwd; - /* - * If set, this flag indicates that the child should be spawned in a detached - * state. - */ - int detached; - /* * TODO describe how this works. */ diff --git a/src/unix/core.c b/src/unix/core.c index e91602ca..93345a3b 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -239,6 +239,7 @@ void uv__finish_close(uv_handle_t* handle) { uv_loop_t* loop = handle->loop; assert(handle->flags & UV_CLOSING); + assert(!(handle->flags & UV_CLOSED)); handle->flags |= UV_CLOSED; switch (handle->type) { diff --git a/src/unix/process.c b/src/unix/process.c index 9e8bd22f..431f4d8c 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -25,7 +25,6 @@ #include #include #include -#include #include /* O_CLOEXEC, O_NONBLOCK */ #include #include @@ -42,11 +41,6 @@ extern char **environ; #endif -#ifndef MAP_ANONYMOUS -#ifdef MAP_ANON -#define MAP_ANONYMOUS MAP_ANON -#endif -#endif static void uv__chld(EV_P_ ev_child* watcher, int revents) { int status = watcher->rstatus; @@ -163,9 +157,6 @@ static int uv__process_init_pipe(uv_pipe_t* handle, int fds[2], int flags) { return uv__make_pipe(fds, flags); } -void _detach_cb() { - /* TODO: Does something need to happen here? */ -} #ifndef SPAWN_WAIT_EXEC # define SPAWN_WAIT_EXEC 1 @@ -188,44 +179,26 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, int status; pid_t pid; int flags; - int *pid_map; uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); loop->counters.process_init++; process->exit_cb = options.exit_cb; - if (options.detached) { - pid_map = mmap(0, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (pid_map == MAP_FAILED) { - goto error; - } - if (options.stdin_stream) { - uv_close((uv_handle_t*)options.stdin_stream, _detach_cb); - } - if (options.stdout_stream) { - uv_close((uv_handle_t*)options.stdout_stream, _detach_cb); - } - if (options.stderr_stream) { - uv_close((uv_handle_t*)options.stderr_stream, _detach_cb); - } - } else { - if (options.stdin_stream && - uv__process_init_pipe(options.stdin_stream, stdin_pipe, 0)) { - goto error; - } - - if (options.stdout_stream && - uv__process_init_pipe(options.stdout_stream, stdout_pipe, 0)) { - goto error; - } - - if (options.stderr_stream && - uv__process_init_pipe(options.stderr_stream, stderr_pipe, 0)) { - goto error; - } + if (options.stdin_stream && + uv__process_init_pipe(options.stdin_stream, stdin_pipe, 0)) { + goto error; } + if (options.stdout_stream && + uv__process_init_pipe(options.stdout_stream, stdout_pipe, 0)) { + goto error; + } + + if (options.stderr_stream && + uv__process_init_pipe(options.stderr_stream, stderr_pipe, 0)) { + goto error; + } /* This pipe is used by the parent to wait until * the child has called `execve()`. We need this @@ -291,21 +264,6 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, uv__nonblock(STDERR_FILENO, 0); } - if (options.detached) { - setsid(); - umask(027); - pid = fork(); - if (pid < 0) { - perror("Second fork()"); - _exit(errno); - } else if (pid > 0) { - /* First child saves the pid of the second child and exits. */ - pid_map[0] = pid; - exit(0); - } - /* Second child continues below */ - } - if (options.cwd && chdir(options.cwd)) { perror("chdir()"); _exit(127); @@ -339,14 +297,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, uv__close(signal_pipe[0]); #endif - if (options.detached) { - process->pid = pid_map[0]; - if (munmap(pid_map, sizeof(pid_t)) != 0) { - goto error; - } - } else { - process->pid = pid; - } + process->pid = pid; ev_child_init(&process->child_watcher, uv__chld, pid, 0); ev_child_start(process->loop->ev, &process->child_watcher); diff --git a/src/win/process.c b/src/win/process.c index 80bfb9ad..84781d63 100644 --- a/src/win/process.c +++ b/src/win/process.c @@ -859,9 +859,6 @@ static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) { return 0; } -void _detach_cb(uv_handle_t *handle) { - /* TODO: something here? */ -} int uv_spawn(uv_loop_t* loop, uv_process_t* process, uv_process_options_t options) { @@ -874,7 +871,6 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, HANDLE* child_stdio = process->child_stdio; STARTUPINFOW startup; PROCESS_INFORMATION info; - DWORD process_flags; if (!options.file) { uv__set_artificial_error(loop, UV_EINVAL); @@ -906,25 +902,6 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, } } - if (options.detached) { - if (options.stdin_stream) { - uv_close((uv_handle_t*)options.stdin_stream, _detach_cb); - options.stdin_stream = NULL; - } - if (options.stdout_stream) { - uv_close((uv_handle_t*)options.stdout_stream, _detach_cb); - options.stdout_stream = NULL; - } - if (options.stderr_stream) { - uv_close((uv_handle_t*)options.stderr_stream, _detach_cb); - options.stderr_stream = NULL; - } - process_flags = CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW | - CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS; - } else { - process_flags = CREATE_UNICODE_ENVIRONMENT; - } - /* Get PATH env. variable. */ size = GetEnvironmentVariableW(L"PATH", NULL, 0) + 1; path = (wchar_t*)malloc(size * sizeof(wchar_t)); @@ -963,7 +940,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0); } - } else if (!options.detached) { + } else { err = duplicate_std_handle(loop, STD_INPUT_HANDLE, &child_stdio[0]); } if (err) { @@ -977,7 +954,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, PIPE_ACCESS_INBOUND, GENERIC_WRITE, 0); - } else if (!options.detached) { + } else { err = duplicate_std_handle(loop, STD_OUTPUT_HANDLE, &child_stdio[1]); } if (err) { @@ -992,7 +969,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, PIPE_ACCESS_INBOUND, GENERIC_WRITE, 0); - } else if (!options.detached) { + } else { err = duplicate_std_handle(loop, STD_ERROR_HANDLE, &child_stdio[2]); } if (err) { @@ -1003,23 +980,19 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; - if (options.detached) { - startup.dwFlags = NULL; - } else { - startup.dwFlags = STARTF_USESTDHANDLES; - } + startup.dwFlags = STARTF_USESTDHANDLES; startup.cbReserved2 = 0; startup.lpReserved2 = NULL; - startup.hStdInput = options.detached ? NULL : child_stdio[0]; - startup.hStdOutput = options.detached ? NULL : child_stdio[1]; - startup.hStdError = options.detached ? NULL : child_stdio[2]; + startup.hStdInput = child_stdio[0]; + startup.hStdOutput = child_stdio[1]; + startup.hStdError = child_stdio[2]; if (CreateProcessW(application_path, arguments, NULL, NULL, - options.detached ? 0 : 1, - process_flags, + 1, + CREATE_UNICODE_ENVIRONMENT, env, cwd, &startup, @@ -1033,20 +1006,16 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, options.stdin_stream->ipc_pid = info.dwProcessId; } - if (!options.detached) { - result = RegisterWaitForSingleObject(&process->wait_handle, - process->process_handle, exit_wait_callback, (void*)process, INFINITE, - WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); - if (!result) { - uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); - } - } - CloseHandle(info.hThread); - if (options.detached) { - CloseHandle(info.hProcess); - exit_wait_callback((void*)process, FALSE); + /* Setup notifications for when the child process exits. */ + result = RegisterWaitForSingleObject(&process->wait_handle, + process->process_handle, exit_wait_callback, (void*)process, INFINITE, + WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); + if (!result) { + uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } + CloseHandle(info.hThread); + } else { /* CreateProcessW failed, but this failure should be delivered */ /* asynchronously to retain unix compatibility. So pretend spawn */ diff --git a/test/test-list.h b/test/test-list.h index 08e26c35..99932da5 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -104,7 +104,6 @@ TEST_DECLARE (spawn_exit_code) TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) TEST_DECLARE (spawn_and_kill) -TEST_DECLARE (spawn_detached) TEST_DECLARE (spawn_and_kill_with_std) TEST_DECLARE (spawn_and_ping) TEST_DECLARE (kill) @@ -280,7 +279,6 @@ TASK_LIST_START TEST_ENTRY (spawn_stdout) TEST_ENTRY (spawn_stdin) TEST_ENTRY (spawn_and_kill) - TEST_ENTRY (spawn_detached) TEST_ENTRY (spawn_and_kill_with_std) TEST_ENTRY (spawn_and_ping) TEST_ENTRY (kill) diff --git a/test/test-spawn.c b/test/test-spawn.c index 83b0bdf2..a4d69437 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -77,22 +77,6 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) { ASSERT(err.code == UV_ESRCH); } -static void detach_cb(uv_process_t* process, int exit_status, int term_signal) { - uv_err_t err; - printf("detach_cb\n"); - exit_cb_called++; - ASSERT(exit_status == 0); - uv_close((uv_handle_t*)process, close_cb); - - /* - * Unlike other tests, this one needs to make sure the process *is* - * still alive. - */ - err = uv_kill(process->pid, 0); - ASSERT(err.code == 0); - err = uv_kill(process->pid, 15); - ASSERT(err.code == 0); -} static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) { uv_buf_t buf; @@ -246,24 +230,6 @@ TEST_IMPL(spawn_and_kill) { return 0; } -TEST_IMPL(spawn_detached) { - int r; - - init_process_options("spawn_helper4", detach_cb); - - options.detached = 1; - - r = uv_spawn(uv_default_loop(), &process, options); - ASSERT(r == 0); - - r = uv_run(uv_default_loop()); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - return 0; -} TEST_IMPL(spawn_and_kill_with_std) { int r;