mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Merge remote-tracking branch 'yawning/feature15435'
This commit is contained in:
commit
aa7b792250
5
changes/feature15435
Normal file
5
changes/feature15435
Normal file
@ -0,0 +1,5 @@
|
||||
o Minor features (pluggable Transports):
|
||||
- When launching managed pluggable transports, setup a valid open stdin
|
||||
in the child process that can be used to detect if tor has terminated.
|
||||
The "TOR_PT_EXIT_ON_STDIN_CLOSE" enviornment variable can be used by
|
||||
implementations to detect this new behavior. Resolves ticket 15435.
|
@ -3942,9 +3942,11 @@ process_handle_new(void)
|
||||
process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t));
|
||||
|
||||
#ifdef _WIN32
|
||||
out->stdin_pipe = INVALID_HANDLE_VALUE;
|
||||
out->stdout_pipe = INVALID_HANDLE_VALUE;
|
||||
out->stderr_pipe = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
out->stdin_pipe = -1;
|
||||
out->stdout_pipe = -1;
|
||||
out->stderr_pipe = -1;
|
||||
#endif
|
||||
@ -3984,7 +3986,7 @@ process_handle_waitpid_cb(int status, void *arg)
|
||||
#define CHILD_STATE_FORK 3
|
||||
#define CHILD_STATE_DUPOUT 4
|
||||
#define CHILD_STATE_DUPERR 5
|
||||
#define CHILD_STATE_REDIRECT 6
|
||||
#define CHILD_STATE_DUPIN 6
|
||||
#define CHILD_STATE_CLOSEFD 7
|
||||
#define CHILD_STATE_EXEC 8
|
||||
#define CHILD_STATE_FAILEXEC 9
|
||||
@ -4018,6 +4020,8 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
HANDLE stdout_pipe_write = NULL;
|
||||
HANDLE stderr_pipe_read = NULL;
|
||||
HANDLE stderr_pipe_write = NULL;
|
||||
HANDLE stdin_pipe_read = NULL;
|
||||
HANDLE stdin_pipe_write = NULL;
|
||||
process_handle_t *process_handle;
|
||||
int status;
|
||||
|
||||
@ -4063,6 +4067,20 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set up pipe for stdin */
|
||||
if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, &saAttr, 0)) {
|
||||
log_warn(LD_GENERAL,
|
||||
"Failed to create pipe for stdin communication with child process: %s",
|
||||
format_win32_error(GetLastError()));
|
||||
return status;
|
||||
}
|
||||
if (!SetHandleInformation(stderr_pipe_write, HANDLE_FLAG_INHERIT, 0)) {
|
||||
log_warn(LD_GENERAL,
|
||||
"Failed to configure pipe for stdin communication with child "
|
||||
"process: %s", format_win32_error(GetLastError()));
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Create the child process */
|
||||
|
||||
/* Windows expects argv to be a whitespace delimited string, so join argv up
|
||||
@ -4077,7 +4095,7 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
siStartInfo.cb = sizeof(STARTUPINFO);
|
||||
siStartInfo.hStdError = stderr_pipe_write;
|
||||
siStartInfo.hStdOutput = stdout_pipe_write;
|
||||
siStartInfo.hStdInput = NULL;
|
||||
siStartInfo.hStdInput = stdin_pipe_read;
|
||||
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
|
||||
/* Create the child process */
|
||||
@ -4107,6 +4125,7 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
/* TODO: Close hProcess and hThread in process_handle->pid? */
|
||||
process_handle->stdout_pipe = stdout_pipe_read;
|
||||
process_handle->stderr_pipe = stderr_pipe_read;
|
||||
process_handle->stdin_pipe = stdin_pipe_write;
|
||||
status = process_handle->status = PROCESS_STATUS_RUNNING;
|
||||
}
|
||||
|
||||
@ -4117,6 +4136,7 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
pid_t pid;
|
||||
int stdout_pipe[2];
|
||||
int stderr_pipe[2];
|
||||
int stdin_pipe[2];
|
||||
int fd, retval;
|
||||
ssize_t nbytes;
|
||||
process_handle_t *process_handle;
|
||||
@ -4141,7 +4161,7 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
|
||||
child_state = CHILD_STATE_PIPE;
|
||||
|
||||
/* Set up pipe for redirecting stdout and stderr of child */
|
||||
/* Set up pipe for redirecting stdout, stderr, and stdin of child */
|
||||
retval = pipe(stdout_pipe);
|
||||
if (-1 == retval) {
|
||||
log_warn(LD_GENERAL,
|
||||
@ -4162,6 +4182,20 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
return status;
|
||||
}
|
||||
|
||||
retval = pipe(stdin_pipe);
|
||||
if (-1 == retval) {
|
||||
log_warn(LD_GENERAL,
|
||||
"Failed to set up pipe for stdin communication with child process: %s",
|
||||
strerror(errno));
|
||||
|
||||
close(stdout_pipe[0]);
|
||||
close(stdout_pipe[1]);
|
||||
close(stderr_pipe[0]);
|
||||
close(stderr_pipe[1]);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
child_state = CHILD_STATE_MAXFD;
|
||||
|
||||
#ifdef _SC_OPEN_MAX
|
||||
@ -4206,13 +4240,11 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
if (-1 == retval)
|
||||
goto error;
|
||||
|
||||
child_state = CHILD_STATE_REDIRECT;
|
||||
child_state = CHILD_STATE_DUPIN;
|
||||
|
||||
/* Link stdin to /dev/null */
|
||||
fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */
|
||||
if (fd != -1)
|
||||
dup2(fd, STDIN_FILENO);
|
||||
else
|
||||
/* Link child stdin to the read end of the pipe */
|
||||
retval = dup2(stdin_pipe[0], STDIN_FILENO);
|
||||
if (-1 == retval)
|
||||
goto error;
|
||||
|
||||
child_state = CHILD_STATE_CLOSEFD;
|
||||
@ -4221,7 +4253,8 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
close(stderr_pipe[1]);
|
||||
close(stdout_pipe[0]);
|
||||
close(stdout_pipe[1]);
|
||||
close(fd);
|
||||
close(stdin_pipe[0]);
|
||||
close(stdin_pipe[1]);
|
||||
|
||||
/* Close all other fds, including the read end of the pipe */
|
||||
/* XXX: We should now be doing enough FD_CLOEXEC setting to make
|
||||
@ -4273,6 +4306,8 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
|
||||
if (-1 == pid) {
|
||||
log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
|
||||
close(stdin_pipe[0]);
|
||||
close(stdin_pipe[1]);
|
||||
close(stdout_pipe[0]);
|
||||
close(stdout_pipe[1]);
|
||||
close(stderr_pipe[0]);
|
||||
@ -4309,16 +4344,28 @@ tor_spawn_background(const char *const filename, const char **argv,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
/* Return write end of the stdin pipe to caller, and close the read end */
|
||||
process_handle->stdin_pipe = stdin_pipe[1];
|
||||
retval = close(stdin_pipe[0]);
|
||||
|
||||
if (-1 == retval) {
|
||||
log_warn(LD_GENERAL,
|
||||
"Failed to close read end of stdin pipe in parent process: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
status = process_handle->status = PROCESS_STATUS_RUNNING;
|
||||
/* Set stdout/stderr pipes to be non-blocking */
|
||||
/* Set stdin/stdout/stderr pipes to be non-blocking */
|
||||
if (fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK) < 0 ||
|
||||
fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK) < 0) {
|
||||
log_warn(LD_GENERAL, "Failed to set stderror/stdout pipes nonblocking "
|
||||
"in parent process: %s", strerror(errno));
|
||||
fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK) < 0 ||
|
||||
fcntl(process_handle->stdin_pipe, F_SETFL, O_NONBLOCK) < 0) {
|
||||
log_warn(LD_GENERAL, "Failed to set stderror/stdout/stdin pipes "
|
||||
"nonblocking in parent process: %s", strerror(errno));
|
||||
}
|
||||
/* Open the buffered IO streams */
|
||||
process_handle->stdout_handle = fdopen(process_handle->stdout_pipe, "r");
|
||||
process_handle->stderr_handle = fdopen(process_handle->stderr_pipe, "r");
|
||||
process_handle->stdin_handle = fdopen(process_handle->stdin_pipe, "r");
|
||||
|
||||
*process_handle_out = process_handle;
|
||||
return process_handle->status;
|
||||
@ -4361,6 +4408,9 @@ tor_process_handle_destroy,(process_handle_t *process_handle,
|
||||
|
||||
if (process_handle->stderr_pipe)
|
||||
CloseHandle(process_handle->stderr_pipe);
|
||||
|
||||
if (process_handle->stdin_pipe)
|
||||
CloseHandle(process_handle->stdin_pipe);
|
||||
#else
|
||||
if (process_handle->stdout_handle)
|
||||
fclose(process_handle->stdout_handle);
|
||||
@ -4368,6 +4418,9 @@ tor_process_handle_destroy,(process_handle_t *process_handle,
|
||||
if (process_handle->stderr_handle)
|
||||
fclose(process_handle->stderr_handle);
|
||||
|
||||
if (process_handle->stdin_handle)
|
||||
fclose(process_handle->stdin_handle);
|
||||
|
||||
clear_waitpid_callback(process_handle->waitpid_cb);
|
||||
#endif
|
||||
|
||||
|
@ -474,12 +474,15 @@ struct process_handle_t {
|
||||
/** One of the PROCESS_STATUS_* values */
|
||||
int status;
|
||||
#ifdef _WIN32
|
||||
HANDLE stdin_pipe;
|
||||
HANDLE stdout_pipe;
|
||||
HANDLE stderr_pipe;
|
||||
PROCESS_INFORMATION pid;
|
||||
#else
|
||||
int stdin_pipe;
|
||||
int stdout_pipe;
|
||||
int stderr_pipe;
|
||||
FILE *stdin_handle;
|
||||
FILE *stdout_handle;
|
||||
FILE *stderr_handle;
|
||||
pid_t pid;
|
||||
|
@ -1388,6 +1388,11 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
|
||||
} else {
|
||||
smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
|
||||
}
|
||||
|
||||
/* All new versions of tor will keep stdin open, so PTs can use it
|
||||
* as a reliable termination detection mechanism.
|
||||
*/
|
||||
smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
|
||||
} else {
|
||||
/* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
|
||||
* TOR_PT_PROXY line.
|
||||
|
@ -107,9 +107,11 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
|
||||
#ifdef _WIN32
|
||||
tt_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE);
|
||||
tt_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE);
|
||||
tt_assert(process_handle->stdin_pipe != INVALID_HANDLE_VALUE);
|
||||
#else
|
||||
tt_assert(process_handle->stdout_pipe >= 0);
|
||||
tt_assert(process_handle->stderr_pipe >= 0);
|
||||
tt_assert(process_handle->stdin_pipe >= 0);
|
||||
#endif
|
||||
|
||||
/* Check stdout */
|
||||
|
Loading…
Reference in New Issue
Block a user