mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 12:23:32 +01:00
Use waitpid code to learn when a controlled process dies
This lets us avoid sending SIGTERM to something that has already died, since we realize it has already died, and is a fix for the unix version of #8746.
This commit is contained in:
parent
4ed03965a5
commit
f8344c2d28
@ -26,6 +26,7 @@
|
||||
#include "address.h"
|
||||
#include "sandbox.h"
|
||||
#include "backtrace.h"
|
||||
#include "util_process.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
@ -3642,7 +3643,10 @@ tor_terminate_process(process_handle_t *process_handle)
|
||||
return 0;
|
||||
}
|
||||
#else /* Unix */
|
||||
if (process_handle->waitpid_cb) {
|
||||
/* We haven't got a waitpid yet, so we can just kill off the process. */
|
||||
return kill(process_handle->pid, SIGTERM);
|
||||
}
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
@ -3691,6 +3695,23 @@ process_handle_new(void)
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/** Invoked when a process that we've launched via tor_spawn_background() has
|
||||
* been found to have terminated.
|
||||
*/
|
||||
static void
|
||||
process_handle_waitpid_cb(int status, void *arg)
|
||||
{
|
||||
process_handle_t *process_handle = arg;
|
||||
|
||||
process_handle->waitpid_exit_status = status;
|
||||
clear_waitpid_callback(process_handle->waitpid_cb);
|
||||
if (process_handle->status == PROCESS_STATUS_RUNNING)
|
||||
process_handle->status = PROCESS_STATUS_NOTRUNNING;
|
||||
process_handle->waitpid_cb = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name child-process states
|
||||
*
|
||||
@ -4007,6 +4028,10 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
process_handle->waitpid_cb = set_waitpid_callback(pid,
|
||||
process_handle_waitpid_cb,
|
||||
process_handle);
|
||||
|
||||
process_handle->stderr_pipe = stderr_pipe[0];
|
||||
retval = close(stderr_pipe[1]);
|
||||
|
||||
@ -4071,6 +4096,8 @@ tor_process_handle_destroy,(process_handle_t *process_handle,
|
||||
|
||||
if (process_handle->stderr_handle)
|
||||
fclose(process_handle->stderr_handle);
|
||||
|
||||
clear_waitpid_callback(process_handle->waitpid_cb);
|
||||
#endif
|
||||
|
||||
memset(process_handle, 0x0f, sizeof(process_handle_t));
|
||||
@ -4088,7 +4115,7 @@ tor_process_handle_destroy,(process_handle_t *process_handle,
|
||||
* probably not work in Tor, because waitpid() is called in main.c to reap any
|
||||
* terminated child processes.*/
|
||||
int
|
||||
tor_get_exit_code(const process_handle_t *process_handle,
|
||||
tor_get_exit_code(process_handle_t *process_handle,
|
||||
int block, int *exit_code)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@ -4128,7 +4155,20 @@ tor_get_exit_code(const process_handle_t *process_handle,
|
||||
int stat_loc;
|
||||
int retval;
|
||||
|
||||
if (process_handle->waitpid_cb) {
|
||||
/* We haven't processed a SIGCHLD yet. */
|
||||
retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG);
|
||||
if (retval == process_handle->pid) {
|
||||
clear_waitpid_callback(process_handle->waitpid_cb);
|
||||
process_handle->waitpid_cb = NULL;
|
||||
process_handle->waitpid_exit_status = stat_loc;
|
||||
}
|
||||
} else {
|
||||
/* We already got a SIGCHLD for this process, and handled it. */
|
||||
retval = process_handle->pid;
|
||||
stat_loc = process_handle->waitpid_exit_status;
|
||||
}
|
||||
|
||||
if (!block && 0 == retval) {
|
||||
/* Process has not exited */
|
||||
return PROCESS_EXIT_RUNNING;
|
||||
|
@ -446,6 +446,7 @@ void set_environment_variable_in_smartlist(struct smartlist_t *env_vars,
|
||||
#define PROCESS_STATUS_ERROR -1
|
||||
|
||||
#ifdef UTIL_PRIVATE
|
||||
struct waitpid_callback_t;
|
||||
/** Structure to represent the state of a process with which Tor is
|
||||
* communicating. The contents of this structure are private to util.c */
|
||||
struct process_handle_t {
|
||||
@ -461,6 +462,12 @@ struct process_handle_t {
|
||||
FILE *stdout_handle;
|
||||
FILE *stderr_handle;
|
||||
pid_t pid;
|
||||
/** If the process has not given us a SIGCHLD yet, this has the
|
||||
* waitpid_callback_t that gets invoked once it has. Otherwise this
|
||||
* contains NULL. */
|
||||
struct waitpid_callback_t *waitpid_cb;
|
||||
/** The exit status reported by waitpid. */
|
||||
int waitpid_exit_status;
|
||||
#endif // _WIN32
|
||||
};
|
||||
#endif
|
||||
@ -469,7 +476,7 @@ struct process_handle_t {
|
||||
#define PROCESS_EXIT_RUNNING 1
|
||||
#define PROCESS_EXIT_EXITED 0
|
||||
#define PROCESS_EXIT_ERROR -1
|
||||
int tor_get_exit_code(const process_handle_t *process_handle,
|
||||
int tor_get_exit_code(process_handle_t *process_handle,
|
||||
int block, int *exit_code);
|
||||
int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
|
||||
#ifdef _WIN32
|
||||
|
Loading…
Reference in New Issue
Block a user