summaryrefslogtreecommitdiffstats
path: root/src/spawn/spawn_client.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/spawn/spawn_client.c250
1 files changed, 0 insertions, 250 deletions
diff --git a/src/spawn/spawn_client.c b/src/spawn/spawn_client.c
deleted file mode 100644
index f2af9842..00000000
--- a/src/spawn/spawn_client.c
+++ /dev/null
@@ -1,250 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "spawn.h"
-
-static uv_process_t process;
-static uv_pipe_t spawn_channel;
-static uv_loop_t *loop;
-uv_async_t spawn_async;
-
-static char prot_buffer[MAX_COMMAND_LENGTH];
-static unsigned prot_buffer_len = 0;
-
-static void async_cb(uv_async_t *handle)
-{
- uv_stop(handle->loop);
-}
-
-static void after_pipe_write(uv_write_t* req, int status)
-{
- (void)status;
-#ifdef SPAWN_DEBUG
- netdata_log_info("CLIENT %s called status=%d", __func__, status);
-#endif
- void **data = req->data;
- freez(data[0]);
- freez(data[1]);
- freez(data);
-}
-
-static void client_parse_spawn_protocol(unsigned source_len, char *source)
-{
- unsigned required_len;
- struct spawn_prot_header *header;
- struct spawn_prot_spawn_result *spawn_result;
- struct spawn_prot_cmd_exit_status *exit_status;
- struct spawn_cmd_info *cmdinfo;
-
- while (source_len) {
- required_len = sizeof(*header);
- if (prot_buffer_len < required_len)
- copy_to_prot_buffer(prot_buffer, &prot_buffer_len, required_len - prot_buffer_len, &source, &source_len);
- if (prot_buffer_len < required_len)
- return; /* Source buffer ran out */
-
- header = (struct spawn_prot_header *)prot_buffer;
- cmdinfo = (struct spawn_cmd_info *)header->handle;
- fatal_assert(NULL != cmdinfo);
-
- switch(header->opcode) {
- case SPAWN_PROT_SPAWN_RESULT:
- required_len += sizeof(*spawn_result);
- if (prot_buffer_len < required_len)
- copy_to_prot_buffer(prot_buffer, &prot_buffer_len, required_len - prot_buffer_len, &source, &source_len);
- if (prot_buffer_len < required_len)
- return; /* Source buffer ran out */
-
- spawn_result = (struct spawn_prot_spawn_result *)(header + 1);
- uv_mutex_lock(&cmdinfo->mutex);
- cmdinfo->pid = spawn_result->exec_pid;
- if (0 == cmdinfo->pid) { /* Failed to spawn */
-#ifdef SPAWN_DEBUG
- netdata_log_info("CLIENT %s SPAWN_PROT_SPAWN_RESULT failed to spawn.", __func__);
-#endif
- cmdinfo->flags |= SPAWN_CMD_FAILED_TO_SPAWN | SPAWN_CMD_DONE;
- uv_cond_signal(&cmdinfo->cond);
- } else {
- cmdinfo->exec_run_timestamp = spawn_result->exec_run_timestamp;
- cmdinfo->flags |= SPAWN_CMD_IN_PROGRESS;
-#ifdef SPAWN_DEBUG
- netdata_log_info("CLIENT %s SPAWN_PROT_SPAWN_RESULT in progress.", __func__);
-#endif
- }
- uv_mutex_unlock(&cmdinfo->mutex);
- prot_buffer_len = 0;
- break;
- case SPAWN_PROT_CMD_EXIT_STATUS:
- required_len += sizeof(*exit_status);
- if (prot_buffer_len < required_len)
- copy_to_prot_buffer(prot_buffer, &prot_buffer_len, required_len - prot_buffer_len, &source, &source_len);
- if (prot_buffer_len < required_len)
- return; /* Source buffer ran out */
-
- exit_status = (struct spawn_prot_cmd_exit_status *)(header + 1);
- uv_mutex_lock(&cmdinfo->mutex);
- cmdinfo->exit_status = exit_status->exec_exit_status;
-#ifdef SPAWN_DEBUG
- netdata_log_info("CLIENT %s SPAWN_PROT_CMD_EXIT_STATUS %d.", __func__, exit_status->exec_exit_status);
-#endif
- cmdinfo->flags |= SPAWN_CMD_DONE;
- uv_cond_signal(&cmdinfo->cond);
- uv_mutex_unlock(&cmdinfo->mutex);
- prot_buffer_len = 0;
- break;
- default:
- fatal_assert(0);
- break;
- }
-
- }
-}
-
-static void on_pipe_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf)
-{
- if (0 == nread) {
- netdata_log_info("%s: Zero bytes read from spawn pipe.", __func__);
- } else if (UV_EOF == nread) {
- netdata_log_info("EOF found in spawn pipe.");
- } else if (nread < 0) {
- netdata_log_error("%s: %s", __func__, uv_strerror(nread));
- }
-
- if (nread < 0) { /* stop stream due to EOF or error */
- (void)uv_read_stop((uv_stream_t *)pipe);
- } else if (nread) {
-#ifdef SPAWN_DEBUG
- netdata_log_info("CLIENT %s read %u", __func__, (unsigned)nread);
-#endif
- client_parse_spawn_protocol(nread, buf->base);
- }
- if (buf && buf->len) {
- freez(buf->base);
- }
-
- if (nread < 0) {
- uv_close((uv_handle_t *)pipe, NULL);
- }
-}
-
-static void on_read_alloc(uv_handle_t* handle,
- size_t suggested_size,
- uv_buf_t* buf)
-{
- (void)handle;
- buf->base = mallocz(suggested_size);
- buf->len = suggested_size;
-}
-
-static void spawn_process_cmd(struct spawn_cmd_info *cmdinfo)
-{
- int ret;
- uv_buf_t *writebuf;
- struct write_context *write_ctx;
-
- void **data = callocz(2, sizeof(void *));
- writebuf = callocz(3, sizeof(uv_buf_t));
- write_ctx = callocz(1, sizeof(*write_ctx));
-
- data[0] = write_ctx;
- data[1] = writebuf;
- write_ctx->write_req.data = data;
-
- uv_mutex_lock(&cmdinfo->mutex);
- cmdinfo->flags |= SPAWN_CMD_PROCESSED;
- uv_mutex_unlock(&cmdinfo->mutex);
-
- write_ctx->header.opcode = SPAWN_PROT_EXEC_CMD;
- write_ctx->header.handle = cmdinfo;
- write_ctx->payload.command_length = strlen(cmdinfo->command_to_run);
-
- writebuf[0] = uv_buf_init((char *)&write_ctx->header, sizeof(write_ctx->header));
- writebuf[1] = uv_buf_init((char *)&write_ctx->payload, sizeof(write_ctx->payload));
- writebuf[2] = uv_buf_init((char *)cmdinfo->command_to_run, write_ctx->payload.command_length);
-
-#ifdef SPAWN_DEBUG
- netdata_log_info("CLIENT %s SPAWN_PROT_EXEC_CMD %u", __func__, (unsigned)cmdinfo->serial);
-#endif
- ret = uv_write(&write_ctx->write_req, (uv_stream_t *)&spawn_channel, writebuf, 3, after_pipe_write);
- fatal_assert(ret == 0);
-}
-
-void spawn_client(void *arg)
-{
- uv_thread_set_name_np("DAEMON_SPAWN");
-
- int ret;
- struct completion *completion = (struct completion *)arg;
-
- loop = mallocz(sizeof(uv_loop_t));
- ret = uv_loop_init(loop);
- if (ret) {
- netdata_log_error("uv_loop_init(): %s", uv_strerror(ret));
- spawn_thread_error = ret;
- goto error_after_loop_init;
- }
- loop->data = NULL;
-
- spawn_async.data = NULL;
- ret = uv_async_init(loop, &spawn_async, async_cb);
- if (ret) {
- netdata_log_error("uv_async_init(): %s", uv_strerror(ret));
- spawn_thread_error = ret;
- goto error_after_async_init;
- }
-
- ret = uv_pipe_init(loop, &spawn_channel, 1);
- if (ret) {
- netdata_log_error("uv_pipe_init(): %s", uv_strerror(ret));
- spawn_thread_error = ret;
- goto error_after_pipe_init;
- }
- fatal_assert(spawn_channel.ipc);
-
- ret = create_spawn_server(loop, &spawn_channel, &process);
- if (ret) {
- netdata_log_error("Failed to fork spawn server process.");
- spawn_thread_error = ret;
- goto error_after_spawn_server;
- }
-
- spawn_thread_error = 0;
- spawn_thread_shutdown = 0;
- /* wake up initialization thread */
- completion_mark_complete(completion);
-
- prot_buffer_len = 0;
- ret = uv_read_start((uv_stream_t *)&spawn_channel, on_read_alloc, on_pipe_read);
- fatal_assert(ret == 0);
-
- while (spawn_thread_shutdown == 0) {
- struct spawn_cmd_info *cmdinfo;
-
- uv_run(loop, UV_RUN_DEFAULT);
- while (NULL != (cmdinfo = spawn_get_unprocessed_cmd())) {
- spawn_process_cmd(cmdinfo);
- }
- }
- /* cleanup operations of the event loop */
- netdata_log_info("Shutting down spawn client event loop.");
- uv_close((uv_handle_t *)&spawn_channel, NULL);
- uv_close((uv_handle_t *)&spawn_async, NULL);
- uv_run(loop, UV_RUN_DEFAULT); /* flush all libuv handles */
-
- netdata_log_info("Shutting down spawn client loop complete.");
- fatal_assert(0 == uv_loop_close(loop));
-
- return;
-
-error_after_spawn_server:
- uv_close((uv_handle_t *)&spawn_channel, NULL);
-error_after_pipe_init:
- uv_close((uv_handle_t *)&spawn_async, NULL);
-error_after_async_init:
- uv_run(loop, UV_RUN_DEFAULT); /* flush all libuv handles */
- fatal_assert(0 == uv_loop_close(loop));
-error_after_loop_init:
- freez(loop);
-
- /* wake up initialization thread */
- completion_mark_complete(completion);
-}