Commit aa7b7922 authored by Nick Mathewson's avatar Nick Mathewson 🦞
Browse files

Merge remote-tracking branch 'yawning/feature15435'

parents 34fa4ad6 fda61e03
Loading
Loading
Loading
Loading

changes/feature15435

0 → 100644
+5 −0
Original line number Diff line number Diff line
  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.
+67 −14
Original line number Diff line number Diff line
@@ -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

+3 −0
Original line number Diff line number Diff line
@@ -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;
+5 −0
Original line number Diff line number Diff line
@@ -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.
+2 −0
Original line number Diff line number Diff 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 */