fixup!
nodejs relies on pid of dead process to use in hash maps. that is not entirely safe, but also still fairly reasonable to do. So instead keep pid, but just set a flag to record that it is dead.
This commit is contained in:
parent
95c2ba84d1
commit
b15b448e52
@ -172,12 +172,10 @@ Public members
|
||||
|
||||
.. c:member:: int uv_process_t.pid
|
||||
|
||||
The PID of the spawned process if it is alive. It is set after calling
|
||||
:c:func:`uv_spawn` and cleared before calling :c:func:`exit_cb`. The value
|
||||
is unique only while this is non-zero, otherwise, another process handle
|
||||
may have already been reassigned the same number before the callback ran.
|
||||
|
||||
If you call :c:func:`uv_spawn`
|
||||
The PID of the spawned process. It is set after calling :c:func:`uv_spawn`
|
||||
and retains the value even after the process exits. The value is only
|
||||
unique while the process is alive; after exit, another process may be
|
||||
reassigned the same PID.
|
||||
|
||||
.. note::
|
||||
The :c:type:`uv_handle_t` members also apply.
|
||||
@ -272,13 +270,13 @@ API
|
||||
setgid specified, or not having enough memory to allocate for the new
|
||||
process.
|
||||
|
||||
Whether the call succeeds of fails, you must call :c:func:`uv_close` before
|
||||
Whether the call succeeds or fails, you must call :c:func:`uv_close` before
|
||||
freeing the memory of handle (unlike other init function in libuv).
|
||||
|
||||
.. warning::
|
||||
On unix, if `handle->pid != 0` when you call `uv_close`, you will create a
|
||||
zombie that libuv cannot reap. You are responsible for calling
|
||||
`waitpid` later. This is not relevant on Windows.
|
||||
On unix, if the process has not yet exited when you call `uv_close`,
|
||||
you will create a zombie that libuv cannot reap. You are responsible
|
||||
for calling `waitpid` later. This is not relevant on Windows.
|
||||
|
||||
.. versionchanged:: 1.24.0 Added `UV_PROCESS_WINDOWS_HIDE_CONSOLE` and
|
||||
`UV_PROCESS_WINDOWS_HIDE_GUI` flags.
|
||||
|
||||
@ -145,7 +145,7 @@ void uv__wait_children(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
assert(pid == process->pid);
|
||||
process->pid = 0; // pid is no longer valid (or unique)
|
||||
process->flags |= UV_HANDLE_ESRCH; /* pid is no longer valid (or unique) */
|
||||
process->status = status;
|
||||
uv__queue_remove(&process->queue);
|
||||
uv__queue_insert_tail(&pending, &process->queue);
|
||||
@ -1101,7 +1101,7 @@ error:
|
||||
|
||||
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
if (process->pid == 0)
|
||||
if (process->flags & UV_HANDLE_ESRCH)
|
||||
return UV_ESRCH;
|
||||
return uv_kill(process->pid, signum);
|
||||
}
|
||||
@ -1123,9 +1123,9 @@ int uv_kill(int pid, int signum) {
|
||||
|
||||
|
||||
void uv__process_close(uv_process_t* handle) {
|
||||
/* Warning: if handle->pid != 0, the caller is creating a zombie that we
|
||||
* cannot reap. We assume here that it is intentional, and that the user will
|
||||
* be wise and cleanup later. */
|
||||
/* Warning: if UV_HANDLE_ESRCH is not set, the caller is creating a zombie
|
||||
* that we cannot reap. We assume here that it is intentional, and that the
|
||||
* user will be wise and cleanup later. */
|
||||
uv__queue_remove(&handle->queue);
|
||||
uv__handle_stop(handle);
|
||||
#ifdef UV_USE_SIGCHLD
|
||||
|
||||
@ -137,6 +137,7 @@ enum {
|
||||
UV_HANDLE_POLL_SLOW = 0x01000000,
|
||||
|
||||
/* Only used by uv_process_t handles. */
|
||||
UV_HANDLE_ESRCH = 0x01000000,
|
||||
UV_HANDLE_REAP = 0x10000000
|
||||
};
|
||||
|
||||
|
||||
@ -846,7 +846,7 @@ void uv__process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
|
||||
/* Clean-up the process handle eagerly. */
|
||||
CloseHandle(handle->process_handle);
|
||||
handle->process_handle = INVALID_HANDLE_VALUE;
|
||||
handle->pid = 0;
|
||||
handle->flags |= UV_HANDLE_ESRCH;
|
||||
|
||||
/* Set the handle to inactive: no callbacks will be made after the exit
|
||||
* callback. */
|
||||
@ -1370,7 +1370,7 @@ static int uv__kill(HANDLE process_handle, int signum) {
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
int err;
|
||||
|
||||
if (process->process_handle == INVALID_HANDLE_VALUE) {
|
||||
if (process->flags & UV_HANDLE_ESRCH) {
|
||||
return UV_ESRCH;
|
||||
}
|
||||
|
||||
|
||||
@ -84,6 +84,8 @@ static void fail_cb(uv_process_t* process,
|
||||
static void kill_cb(uv_process_t* process,
|
||||
int64_t exit_status,
|
||||
int term_signal) {
|
||||
int err;
|
||||
|
||||
printf("exit_cb\n");
|
||||
exit_cb_called++;
|
||||
#ifdef _WIN32
|
||||
@ -104,6 +106,8 @@ static void kill_cb(uv_process_t* process,
|
||||
uv_close((uv_handle_t*) process, close_cb);
|
||||
|
||||
/*
|
||||
* Sending signum == 0 should check if the
|
||||
* child process is still alive, not kill it.
|
||||
* This process should be dead.
|
||||
*/
|
||||
err = uv_kill(process->pid, 0);
|
||||
@ -200,12 +204,13 @@ 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(process.pid == 0);
|
||||
ASSERT(r == UV_ENOENT || r == UV_EACCES);
|
||||
ASSERT_OK(uv_is_active((uv_handle_t*) &process));
|
||||
ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user