Example #1
0
struct PP_Var nspawn_send_request(struct PP_Var req_var) {
  /*
   * naclprocess.js is required in order send requests to JavaScript.
   * If NACL_PROCESS is not set in the environment then we assume it is
   * not present and exit early. Without this check we would block forever
   * waiting for a response for the JavaScript side.
   *
   * Only check this once per process, as some programs (emacs)
   * engage in manipulation of the environment that may not be safely
   * read at all times.
   */
  static int checked_for_nacl_process = 0;
  if (!checked_for_nacl_process) {
    const char* naclprocess = getenv("NACL_PROCESS");
    if (naclprocess == NULL) {
      fprintf(stderr, "nspawn_send_request called without NACL_PROCESS set\n");
      return PP_MakeNull();
    }
    checked_for_nacl_process = 1;
  }

  int64_t id = get_request_id();
  char req_id[64];
  sprintf(req_id, "%lld", id);
  nspawn_dict_setstring(req_var, "id", req_id);

  struct NaClSpawnReply reply;
  pthread_mutex_init(&reply.mu, NULL);
  pthread_cond_init(&reply.cond, NULL);
  PSEventRegisterMessageHandler(req_id, &handle_reply, &reply);

  PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), req_var);
  nspawn_var_release(req_var);

  pthread_mutex_lock(&reply.mu);
  /*
   * Wait for response for JavaScript.  This can block for an unbounded amount
   * of time (e.g. waiting for a response to waitpid).
   */
  int error = pthread_cond_wait(&reply.cond, &reply.mu);
  pthread_mutex_unlock(&reply.mu);

  pthread_cond_destroy(&reply.cond);
  pthread_mutex_destroy(&reply.mu);

  PSEventRegisterMessageHandler(req_id, NULL, &reply);

  if (error != 0) {
    fprintf(stderr, "nspawn_send_request: pthread_cond_timedwait: %s\n",
          strerror(error));
    return PP_MakeNull();
  }

  return reply.result_var;
}
Example #2
0
void ExitHandshake(int status, void* user_data) {
  if (s_exit_message == NULL)
    return;

  PSEventRegisterMessageHandler(s_exit_message, MessageHandlerExit, NULL);

  /* exit message + ':' + num + \0 */
  size_t message_len = strlen(s_exit_message) + 1 + 11 + 1;
  char* message = alloca(message_len);
  snprintf(message, message_len, "%s:%d", s_exit_message, status);

  pthread_mutex_lock(&s_exit_lock);
  PostMessageString(message);
  pthread_cond_wait(&s_exit_cond, &s_exit_lock);
  pthread_mutex_unlock(&s_exit_lock);
}
Example #3
0
int ProcessProperties(void) {
  /* Reset verbosity if passed in */
  const char* verbosity = getenv("PS_VERBOSITY");
  if (verbosity)
    PSInstanceSetVerbosity(atoi(verbosity));

  /* Enable NaCl IO to map STDIN, STDOUT, and STDERR */
  nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);

  s_tty_prefix = getenv("PS_TTY_PREFIX");
  if (s_tty_prefix) {
    s_tty_fd = open("/dev/tty", O_WRONLY);
    if (s_tty_fd >= 0) {
      PSEventRegisterMessageHandler(s_tty_prefix, MessageHandlerInput, NULL);
      const char* tty_resize = getenv("PS_TTY_RESIZE");
      if (tty_resize)
        PSEventRegisterMessageHandler(tty_resize, MessageHandlerResize, NULL);

      char* tty_rows = getenv("PS_TTY_ROWS");
      char* tty_cols = getenv("PS_TTY_COLS");
      if (tty_rows && tty_cols) {
        char* end = tty_rows;
        int rows = strtol(tty_rows, &end, 10);
        if (*end != '\0' || rows < 0) {
          PSInstanceError("Invalid value for PS_TTY_ROWS: %s\n", tty_rows);
        } else {
          end = tty_cols;
          int cols = strtol(tty_cols, &end, 10);
          if (*end != '\0' || cols < 0)
            PSInstanceError("Invalid value for PS_TTY_COLS: %s\n", tty_cols);
          else
            HandleResize(cols, rows);
        }
      } else if (tty_rows || tty_cols) {
        PSInstanceError("PS_TTY_ROWS and PS_TTY_COLS must be set together\n");
      }

      struct tioc_nacl_output handler;
      handler.handler = TtyOutputHandler;
      handler.user_data = NULL;
      ioctl(s_tty_fd, TIOCNACLOUTPUT, &handler);
    } else {
      PSInstanceError("Failed to open /dev/tty.\n");
    }
  }

  /* Set default values */
  setenv("PS_STDIN", "/dev/stdin", 0);
  setenv("PS_STDOUT", "/dev/stdout", 0);
  setenv("PS_STDERR", "/dev/console3", 0);

  int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
  dup2(fd0, 0);

  int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
  dup2(fd1, 1);

  int fd2 = open(getenv("PS_STDERR"), O_WRONLY);
  dup2(fd2, 2);

  PSEventRegisterMessageHandler("jspipe1", MessageHandlerInput, NULL);
  PSEventRegisterMessageHandler("jspipe2", MessageHandlerInput, NULL);
  PSEventRegisterMessageHandler("jspipe3", MessageHandlerInput, NULL);

  s_exit_message = getenv("PS_EXIT_MESSAGE");

  /* If PS_EXIT_MESSAGE is set in the environment then we perform a handshake
   * with JavaScript when program exits. */
  if (s_exit_message != NULL)
    nacl_io_set_exit_callback(ExitHandshake, NULL);

  /* Set line buffering on stdout and stderr */
#if !defined(WIN32)
  setvbuf(stderr, NULL, _IOLBF, 0);
  setvbuf(stdout, NULL, _IOLBF, 0);
#endif
  return 1;
}