/* 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)); }
/* 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); }
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; }
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; }
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; }
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); } } } }