Browse Source

Add process_terminate().

This patch adds support for process termination to the Process
subsystem.

See: https://bugs.torproject.org/28179
Alexander Færøy 5 years ago
parent
commit
4f611a1df7

+ 20 - 0
src/lib/process/process.c

@@ -255,6 +255,26 @@ process_exec(process_t *process)
   return status;
 }
 
+/** Terminate the given process. Returns true on success,
+ * otherwise false. */
+bool
+process_terminate(process_t *process)
+{
+  tor_assert(process);
+
+  /* Terminating a non-running process isn't going to work. */
+  if (process_get_status(process) != PROCESS_STATUS_RUNNING)
+    return false;
+
+  log_debug(LD_PROCESS, "Terminating process");
+
+#ifndef _WIN32
+  return process_unix_terminate(process);
+#else
+  return process_win32_terminate(process);
+#endif
+}
+
 /** Returns the unique process identifier for the given <b>process</b>. */
 process_pid_t
 process_get_pid(process_t *process)

+ 1 - 0
src/lib/process/process.h

@@ -66,6 +66,7 @@ void process_free_(process_t *process);
 #define process_free(s) FREE_AND_NULL(process_t, process_free_, (s))
 
 process_status_t process_exec(process_t *process);
+bool process_terminate(process_t *process);
 
 process_pid_t process_get_pid(process_t *process);
 

+ 26 - 0
src/lib/process/process_unix.c

@@ -356,6 +356,32 @@ process_unix_exec(process_t *process)
   return PROCESS_STATUS_RUNNING;
 }
 
+/** Terminate the given process. Returns true on success, otherwise false. */
+bool
+process_unix_terminate(process_t *process)
+{
+  tor_assert(process);
+
+  process_unix_t *unix_process = process_get_unix_process(process);
+
+  /* All running processes should have a waitpid. */
+  if (BUG(unix_process->waitpid == NULL))
+    return false;
+
+  /* Send a SIGTERM to our child process. */
+  int ret;
+
+  ret = kill(unix_process->pid, SIGTERM);
+
+  if (ret == -1) {
+    log_warn(LD_PROCESS, "Unable to terminate process: %s",
+             strerror(errno));
+    return false;
+  }
+
+  return ret == 0;
+}
+
 /** Returns the unique process identifier for the given <b>process</b>. */
 process_pid_t
 process_unix_get_pid(process_t *process)

+ 1 - 0
src/lib/process/process_unix.h

@@ -29,6 +29,7 @@ void process_unix_free_(process_unix_t *unix_process);
   FREE_AND_NULL(process_unix_t, process_unix_free_, (s))
 
 process_status_t process_unix_exec(struct process_t *process);
+bool process_unix_terminate(struct process_t *process);
 
 process_pid_t process_unix_get_pid(struct process_t *process);
 

+ 22 - 0
src/lib/process/process_win32.c

@@ -271,6 +271,28 @@ process_win32_exec(process_t *process)
   return PROCESS_STATUS_RUNNING;
 }
 
+/** Terminate the given process. Returns true on success, otherwise false. */
+bool
+process_win32_terminate(process_t *process)
+{
+  tor_assert(process);
+
+  process_win32_t *win32_process = process_get_win32_process(process);
+
+  /* Terminate our process. */
+  BOOL ret;
+
+  ret = TerminateProcess(win32_process->process_information.hProcess, 0);
+
+  if (! ret) {
+    log_warn(LD_PROCESS, "TerminateProcess() failed: %s",
+             format_win32_error(GetLastError()));
+    return false;
+  }
+
+  return true;
+}
+
 /** Returns the unique process identifier for the given <b>process</b>. */
 process_pid_t
 process_win32_get_pid(process_t *process)

+ 1 - 0
src/lib/process/process_win32.h

@@ -33,6 +33,7 @@ void process_win32_init(void);
 void process_win32_deinit(void);
 
 process_status_t process_win32_exec(struct process_t *process);
+bool process_win32_terminate(struct process_t *process);
 
 process_pid_t process_win32_get_pid(struct process_t *process);