This commit is contained in:
Igor Zinkovsky 2011-11-02 14:05:22 -07:00
parent 8d5c64adf5
commit 74b49e821b
10 changed files with 120 additions and 33 deletions

View File

@ -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
*/

View File

@ -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) {

View File

@ -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_;
}
}

View File

@ -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";

View File

@ -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);

View File

@ -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.
*/

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;