Permalink
Browse files

uv_kill

  • Loading branch information...
1 parent 8d5c64a commit 31f94db78e9cf679969ab6d23765de5c101c2db4 Igor Zinkovsky committed Nov 2, 2011
Showing with 114 additions and 22 deletions.
  1. +4 −0 include/uv.h
  2. +11 −0 src/unix/process.c
  3. +54 −21 src/win/process.c
  4. +2 −0 test/test-list.h
  5. +43 −1 test/test-spawn.c
View
@@ -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
@@ -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_;
@ry

ry Nov 2, 2011

Contributor

uv_ok_ is defined in src/win/error.c and src/unix/dl.c. Probably It should be moved to src/common.c and an extern added to common.h?

+ }
+}
View
@@ -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 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
}
-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)) {
+ return uv_ok_;
+ } else {
+ return uv__new_sys_error(GetLastError());
+ }
+ } else if (signum == 0) {
+ /* Health check: is the process still alive? */
+ if (GetExitCodeProcess(process_handle, &status) &&
+ status == STILL_ACTIVE) {
+ return uv_ok_;
+ } else {
+ err.code = UV_EINVAL;
@piscisaureus

piscisaureus Nov 2, 2011

Member

Same as the other comment - there could be other error conditions than EINVAL.

+ return err;
+ }
+ }
@piscisaureus

piscisaureus Nov 2, 2011

Member

Do not ignore other signals, return some error (UV_ENOSYS I think?)

+
+ return uv_ok_;
+}
+
+
+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;
- }
+ err = uv__kill(process->process_handle, signum);
+
+ if (err.code != UV_OK) {
+ uv__set_error(process->loop, err.code, err.sys_errno_);
+ 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;
- }
+
+ 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) {
+ err.code = UV_EINVAL;
@piscisaureus

piscisaureus Nov 2, 2011

Member

Why would always return EINVAL? I assume there may be other reasons a pid can't be opened (e.g. security).

+ return err;
}
- assert(0 && "unreachable");
+ err = uv__kill(process_handle, signum);
+ CloseHandle(process_handle);
+
+ return err;
}
View
@@ -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
@@ -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,15 +56,23 @@ 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
ASSERT(exit_status == 1);
#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_EINVAL);
}
@@ -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;

0 comments on commit 31f94db

Please sign in to comment.