Exemple #1
0
/* get-sockname */
static void cmd_get_sockname(struct watchman_client* client, const json_ref&) {
  auto resp = make_response();

  resp.set("sockname", typed_string_to_json(get_sock_name(), W_STRING_BYTE));

  send_and_dispose_response(client, std::move(resp));
}
Exemple #2
0
/* get-sockname */
void cmd_get_sockname(struct watchman_client *client, json_t *args)
{
  json_t *resp = make_response();

  unused_parameter(args);

  set_prop(resp, "sockname", json_string(get_sock_name()));

  send_and_dispose_response(client, resp);
}
Exemple #3
0
void
boss::Socket::get_sock_name(string & socket_address, uint16_t & socket_port)
{
    struct sockaddr name;
    struct sockaddr_in *p = (struct sockaddr_in *) &name;
    socklen_t namelen = sizeof(name);

    bzero(&name, sizeof(struct sockaddr));
    get_sock_name(name, namelen);

    char addr[INET_ADDRSTRLEN];
    socket_address = inet_ntop(AF_INET, &p->sin_addr, addr, sizeof(addr));
    socket_port = ntohs(p->sin_port);

    return;
}
Exemple #4
0
struct watchman_trigger_command *w_build_trigger_from_def(
  w_root_t *root, json_t *trig, char **errmsg)
{
  struct watchman_trigger_command *cmd;
  json_t *ele, *query;
  json_int_t jint;
  const char *name = NULL;

  cmd = calloc(1, sizeof(*cmd));
  if (!cmd) {
    *errmsg = strdup("no memory");
    return NULL;
  }

  cmd->definition = trig;
  json_incref(cmd->definition);

  query = json_pack("{s:O}", "expression",
      json_object_get(cmd->definition, "expression"));
  cmd->query = w_query_parse(query, errmsg);
  json_decref(query);

  if (!cmd->query) {
    w_trigger_command_free(cmd);
    return NULL;
  }

  json_unpack(trig, "{s:s}", "name", &name);
  if (!name) {
    *errmsg = strdup("invalid or missing name");
    w_trigger_command_free(cmd);
    return NULL;
  }

  cmd->triggername = w_string_new(name);
  cmd->command = json_object_get(trig, "command");
  if (cmd->command) {
    json_incref(cmd->command);
  }
  if (!cmd->command || !json_is_array(cmd->command) ||
      !json_array_size(cmd->command)) {
    *errmsg = strdup("invalid command array");
    w_trigger_command_free(cmd);
    return NULL;
  }

  json_unpack(trig, "{s:b}", "append_files", &cmd->append_files);

  ele = json_object_get(trig, "stdin");
  if (!ele) {
    cmd->stdin_style = input_dev_null;
  } else if (json_is_array(ele)) {
    cmd->stdin_style = input_json;
    if (!parse_field_list(ele, &cmd->field_list, errmsg)) {
      w_trigger_command_free(cmd);
      return NULL;
    }
  } else if (json_is_string(ele)) {
    const char *str = json_string_value(ele);
    if (!strcmp(str, "/dev/null")) {
      cmd->stdin_style = input_dev_null;
    } else if (!strcmp(str, "NAME_PER_LINE")) {
      cmd->stdin_style = input_name_list;
    } else {
      ignore_result(asprintf(errmsg, "invalid stdin value %s", str));
      w_trigger_command_free(cmd);
      return NULL;
    }
  } else {
    *errmsg = strdup("invalid value for stdin");
    w_trigger_command_free(cmd);
    return NULL;
  }

  jint = 0; // unlimited unless specified
  json_unpack(trig, "{s:I}", "max_files_stdin", &jint);
  if (jint < 0) {
    *errmsg = strdup("max_files_stdin must be >= 0");
    w_trigger_command_free(cmd);
    return NULL;
  }
  cmd->max_files_stdin = jint;

  json_unpack(trig, "{s:s}", "stdout", &cmd->stdout_name);
  json_unpack(trig, "{s:s}", "stderr", &cmd->stderr_name);

  if (!parse_redirection(&cmd->stdout_name, &cmd->stdout_flags,
        "stdout", errmsg)) {
    w_trigger_command_free(cmd);
    return NULL;
  }

  if (!parse_redirection(&cmd->stderr_name, &cmd->stderr_flags,
        "stderr", errmsg)) {
    w_trigger_command_free(cmd);
    return NULL;
  }

  // Copy current environment
  cmd->envht = w_envp_make_ht();

  // Set some standard vars
  w_envp_set(cmd->envht, "WATCHMAN_ROOT", root->root_path);
  w_envp_set_cstring(cmd->envht, "WATCHMAN_SOCK", get_sock_name());
  w_envp_set(cmd->envht, "WATCHMAN_TRIGGER", cmd->triggername);

  return cmd;
}
Exemple #5
0
static void *perf_log_thread(void *unused) {
  json_t *samples = NULL;
  char **envp;
  json_t *perf_cmd;
  int64_t sample_batch;

  unused_parameter(unused);

  w_set_thread_name("perflog");

  // Prep some things that we'll need each time we run a command
  {
    uint32_t env_size;
    w_ht_t *envpht = w_envp_make_ht();
    char *statedir = dirname(strdup(watchman_state_file));
    w_envp_set_cstring(envpht, "WATCHMAN_STATE_DIR", statedir);
    w_envp_set_cstring(envpht, "WATCHMAN_SOCK", get_sock_name());
    envp = w_envp_make_from_ht(envpht, &env_size);
  }

  perf_cmd = cfg_get_json(NULL, "perf_logger_command");
  if (json_is_string(perf_cmd)) {
    perf_cmd = json_pack("[O]", perf_cmd);
  }
  if (!json_is_array(perf_cmd)) {
    w_log(
        W_LOG_FATAL,
        "perf_logger_command must be either a string or an array of strings\n");
  }

  sample_batch =
      cfg_get_int(NULL, "perf_logger_command_max_samples_per_call", 4);

  while (true) {
    pthread_mutex_lock(&perf_log_lock);
    if (!perf_log_samples) {
      pthread_cond_wait(&perf_log_cond, &perf_log_lock);
    }
    samples = perf_log_samples;
    perf_log_samples = NULL;

    pthread_mutex_unlock(&perf_log_lock);

    if (samples) {
      while (json_array_size(samples) > 0) {
        int i = 0;
        json_t *cmd = json_array();
        posix_spawnattr_t attr;
        posix_spawn_file_actions_t actions;
        pid_t pid;
        char **argv = NULL;

        json_array_extend(cmd, perf_cmd);

        while (i < sample_batch && json_array_size(samples) > 0) {
          char *stringy = json_dumps(json_array_get(samples, 0), 0);
          json_array_append(cmd, typed_string_to_json(stringy, W_STRING_MIXED));
          free(stringy);
          json_array_remove(samples, 0);
          i++;
        }

        argv = w_argv_copy_from_json(cmd, 0);
        if (!argv) {
          char *dumped = json_dumps(cmd, 0);
          w_log(W_LOG_FATAL, "error converting %s to an argv array\n", dumped);
        }

        posix_spawnattr_init(&attr);
#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
        posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT);
#endif
        posix_spawn_file_actions_init(&actions);
        posix_spawn_file_actions_addopen(&actions, STDIN_FILENO, "/dev/null",
                                         O_RDONLY, 0666);
        posix_spawn_file_actions_addopen(&actions, STDOUT_FILENO, "/dev/null",
                                         O_WRONLY, 0666);
        posix_spawn_file_actions_addopen(&actions, STDERR_FILENO, "/dev/null",
                                         O_WRONLY, 0666);

        if (posix_spawnp(&pid, argv[0], &actions, &attr, argv, envp) == 0) {
          // There's no sense waiting here, because w_reap_children is called
          // by the reaper thread.
        } else {
          int err = errno;
          w_log(W_LOG_ERR, "failed to spawn %s: %s\n", argv[0],
                strerror(err));
        }

        posix_spawnattr_destroy(&attr);
        posix_spawn_file_actions_destroy(&actions);

        free(argv);
        json_decref(cmd);
      }
      json_decref(samples);
    }
  }

  return NULL;
}
Exemple #6
0
void PerfLogThread::loop() {
  json_ref samples;
  char **envp;
  json_ref perf_cmd;
  int64_t sample_batch;

  w_set_thread_name("perflog");

  // Prep some things that we'll need each time we run a command
  {
    uint32_t env_size;
    auto envpht = w_envp_make_ht();
    char *statedir = dirname(strdup(watchman_state_file));
    w_envp_set_cstring(envpht, "WATCHMAN_STATE_DIR", statedir);
    w_envp_set_cstring(envpht, "WATCHMAN_SOCK", get_sock_name());
    envp = w_envp_make_from_ht(envpht, &env_size);
  }

  perf_cmd = cfg_get_json("perf_logger_command");
  if (json_is_string(perf_cmd)) {
    perf_cmd = json_array({perf_cmd});
  }
  if (!json_is_array(perf_cmd)) {
    w_log(
        W_LOG_FATAL,
        "perf_logger_command must be either a string or an array of strings\n");
  }

  sample_batch = cfg_get_int("perf_logger_command_max_samples_per_call", 4);

  while (!w_is_stopping()) {
    {
      auto wlock = samples_.wlock();
      if (!*wlock) {
        cond_.wait(wlock.getUniqueLock());
      }

      samples = nullptr;
      std::swap(samples, *wlock);
    }

    if (samples) {
      while (json_array_size(samples) > 0) {
        int i = 0;
        auto cmd = json_array();
        posix_spawnattr_t attr;
        posix_spawn_file_actions_t actions;
        pid_t pid;
        char **argv = NULL;

        json_array_extend(cmd, perf_cmd);

        while (i < sample_batch && json_array_size(samples) > 0) {
          char *stringy = json_dumps(json_array_get(samples, 0), 0);
          if (stringy) {
            json_array_append_new(
                cmd, typed_string_to_json(stringy, W_STRING_MIXED));
            free(stringy);
          }
          json_array_remove(samples, 0);
          i++;
        }

        argv = w_argv_copy_from_json(cmd, 0);
        if (!argv) {
          char *dumped = json_dumps(cmd, 0);
          w_log(W_LOG_FATAL, "error converting %s to an argv array\n", dumped);
        }

        posix_spawnattr_init(&attr);
#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
        posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT);
#endif
        posix_spawn_file_actions_init(&actions);
        posix_spawn_file_actions_addopen(&actions, STDIN_FILENO, "/dev/null",
                                         O_RDONLY, 0666);
        posix_spawn_file_actions_addopen(&actions, STDOUT_FILENO, "/dev/null",
                                         O_WRONLY, 0666);
        posix_spawn_file_actions_addopen(&actions, STDERR_FILENO, "/dev/null",
                                         O_WRONLY, 0666);

        if (posix_spawnp(&pid, argv[0], &actions, &attr, argv, envp) == 0) {
          int status;
          while (waitpid(pid, &status, 0) != pid) {
            if (errno != EINTR) {
              break;
            }
          }
        } else {
          int err = errno;
          w_log(W_LOG_ERR, "failed to spawn %s: %s\n", argv[0],
                strerror(err));
        }

        posix_spawnattr_destroy(&attr);
        posix_spawn_file_actions_destroy(&actions);

        free(argv);
      }
    }
  }
}