uv_kill
This commit is contained in:
parent
8d5c64adf5
commit
74b49e821b
@ -983,6 +983,10 @@ UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*,
|
||||
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
|
||||
|
||||
|
||||
/* Kills the process with the specified signal. */
|
||||
UV_EXTERN uv_err_t uv_kill(int pid, int signum);
|
||||
|
||||
|
||||
/*
|
||||
* uv_work_t is a subclass of uv_req_t
|
||||
*/
|
||||
|
||||
@ -26,8 +26,6 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
static const uv_err_t uv_ok_ = { UV_OK, 0 };
|
||||
|
||||
uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {
|
||||
void* handle = dlopen(filename, RTLD_LAZY);
|
||||
if (handle == NULL) {
|
||||
|
||||
@ -300,3 +300,14 @@ int uv_process_kill(uv_process_t* process, int signum) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_kill(int pid, int signum) {
|
||||
int r = kill(pid, signum);
|
||||
|
||||
if (r) {
|
||||
return uv__new_sys_error(errno);
|
||||
} else {
|
||||
return uv_ok_;
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +48,9 @@ uv_buf_t uv_buf_init(char* base, size_t len) {
|
||||
}
|
||||
|
||||
|
||||
const uv_err_t uv_ok_ = { UV_OK, 0 };
|
||||
|
||||
|
||||
const char* uv_err_name(uv_err_t err) {
|
||||
switch (err.code) {
|
||||
case UV_UNKNOWN: return "UNKNOWN";
|
||||
|
||||
@ -48,6 +48,8 @@ void uv_add_ares_handle(uv_loop_t* loop, uv_ares_task_t* handle);
|
||||
|
||||
int uv_ares_handles_empty(uv_loop_t* loop);
|
||||
|
||||
extern const uv_err_t uv_ok_;
|
||||
|
||||
uv_err_code uv_translate_sys_error(int sys_errno);
|
||||
void uv__set_error(uv_loop_t* loop, uv_err_code code, int sys_error);
|
||||
void uv__set_sys_error(uv_loop_t* loop, int sys_error);
|
||||
|
||||
@ -30,9 +30,6 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
const uv_err_t uv_ok_ = { UV_OK, ERROR_SUCCESS };
|
||||
|
||||
|
||||
/*
|
||||
* Display an error message and abort the event loop.
|
||||
*/
|
||||
|
||||
@ -286,11 +286,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
|
||||
int uv_parent_pid();
|
||||
|
||||
|
||||
/*
|
||||
* Error handling
|
||||
*/
|
||||
extern const uv_err_t uv_ok_;
|
||||
|
||||
void uv_fatal_error(const int errorno, const char* syscall);
|
||||
|
||||
uv_err_code uv_translate_sys_error(int sys_errno);
|
||||
|
||||
@ -26,8 +26,11 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define SIGKILL 9
|
||||
|
||||
typedef struct env_var {
|
||||
const char* narrow;
|
||||
const wchar_t* wide;
|
||||
@ -1052,35 +1055,65 @@ done:
|
||||
}
|
||||
|
||||
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
static uv_err_t uv__kill(HANDLE process_handle, int signum) {
|
||||
DWORD status;
|
||||
uv_err_t err;
|
||||
|
||||
if (signum == SIGTERM || signum == SIGKILL) {
|
||||
/* Kill the process. On Windows, killed processes normally return 1. */
|
||||
if (TerminateProcess(process_handle, 1)) {
|
||||
err = uv_ok_;
|
||||
} else {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
}
|
||||
} else if (signum == 0) {
|
||||
/* Health check: is the process still alive? */
|
||||
if (GetExitCodeProcess(process_handle, &status) &&
|
||||
status == STILL_ACTIVE) {
|
||||
err = uv_ok_;
|
||||
} else {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
}
|
||||
} else {
|
||||
err.code = UV_ENOSYS;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
uv_err_t err;
|
||||
|
||||
if (process->process_handle == INVALID_HANDLE_VALUE) {
|
||||
uv__set_artificial_error(process->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (signum) {
|
||||
/* Kill the process. On Windows, killed processes normally return 1. */
|
||||
if (TerminateProcess(process->process_handle, 1)) {
|
||||
process->exit_signal = signum;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
uv__set_sys_error(process->loop, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Health check: is the process still alive? */
|
||||
if (GetExitCodeProcess(process->process_handle, &status) && status == STILL_ACTIVE) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
uv__set_artificial_error(process->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
err = uv__kill(process->process_handle, signum);
|
||||
|
||||
if (err.code != UV_OK) {
|
||||
uv__set_error(process->loop, err.code, err.sys_errno_);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(0 && "unreachable");
|
||||
process->exit_signal = signum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_kill(int pid, int signum) {
|
||||
uv_err_t err;
|
||||
HANDLE process_handle = OpenProcess(PROCESS_TERMINATE |
|
||||
PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
|
||||
if (process_handle == INVALID_HANDLE_VALUE) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
err = uv__kill(process_handle, signum);
|
||||
CloseHandle(process_handle);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -89,6 +89,7 @@ TEST_DECLARE (spawn_stdout)
|
||||
TEST_DECLARE (spawn_stdin)
|
||||
TEST_DECLARE (spawn_and_kill)
|
||||
TEST_DECLARE (spawn_and_ping)
|
||||
TEST_DECLARE (kill)
|
||||
TEST_DECLARE (fs_file_noent)
|
||||
TEST_DECLARE (fs_file_async)
|
||||
TEST_DECLARE (fs_file_sync)
|
||||
@ -227,6 +228,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (spawn_stdin)
|
||||
TEST_ENTRY (spawn_and_kill)
|
||||
TEST_ENTRY (spawn_and_ping)
|
||||
TEST_ENTRY (kill)
|
||||
#ifdef _WIN32
|
||||
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
|
||||
TEST_ENTRY (argument_escaping)
|
||||
|
||||
@ -33,6 +33,7 @@ static uv_process_options_t options;
|
||||
static char exepath[1024];
|
||||
static size_t exepath_size = 1024;
|
||||
static char* args[3];
|
||||
static int no_term_signal;
|
||||
|
||||
#define OUTPUT_SIZE 1024
|
||||
static char output[OUTPUT_SIZE];
|
||||
@ -55,6 +56,8 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) {
|
||||
|
||||
|
||||
static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
|
||||
uv_err_t err;
|
||||
|
||||
printf("exit_cb\n");
|
||||
exit_cb_called++;
|
||||
#ifdef _WIN32
|
||||
@ -62,8 +65,14 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
|
||||
#else
|
||||
ASSERT(exit_status == 0);
|
||||
#endif
|
||||
ASSERT(term_signal == 15);
|
||||
ASSERT(no_term_signal || term_signal == 15);
|
||||
uv_close((uv_handle_t*)process, close_cb);
|
||||
|
||||
/* Sending signum == 0 should check if the
|
||||
* child process is still alive, not kill it.
|
||||
*/
|
||||
err = uv_kill(process->pid, 0);
|
||||
ASSERT(err.code != UV_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -261,6 +270,39 @@ TEST_IMPL(spawn_and_ping) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(kill) {
|
||||
int r;
|
||||
uv_err_t err;
|
||||
|
||||
#ifdef _WIN32
|
||||
no_term_signal = 1;
|
||||
#endif
|
||||
|
||||
init_process_options("spawn_helper4", kill_cb);
|
||||
|
||||
r = uv_spawn(uv_default_loop(), &process, options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Sending signum == 0 should check if the
|
||||
* child process is still alive, not kill it.
|
||||
*/
|
||||
err = uv_kill(process.pid, 0);
|
||||
ASSERT(err.code == UV_OK);
|
||||
|
||||
/* Kill the process. */
|
||||
err = uv_kill(process.pid, /* SIGTERM */ 15);
|
||||
ASSERT(err.code == UV_OK);
|
||||
|
||||
r = uv_run(uv_default_loop());
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(exit_cb_called == 1);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
|
||||
int r;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user