diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2022-08-26 05:51:53 +0200 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2022-08-26 05:54:22 +0200 |
commit | 1de2aaa4001eb2d0ddfc4f86ab2c2a3eebdc9841 (patch) | |
tree | 85b0290fd51c220a9a621e98c0b88d92ce776e33 | |
parent | worker: capture process output (diff) | |
download | cimple-1de2aaa4001eb2d0ddfc4f86ab2c2a3eebdc9841.tar.gz cimple-1de2aaa4001eb2d0ddfc4f86ab2c2a3eebdc9841.zip |
worker: allow graceful shutdowns
Well, maybe "graceful" is a strong word, but now you _can_ do
./server &
./worker &
./client ci_run URL REV && kill "$( pidof worker )"
and the worker will wait for the CI run to complete.
-rw-r--r-- | src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/signal.c | 23 | ||||
-rw-r--r-- | src/signal.h | 28 | ||||
-rw-r--r-- | src/worker.c | 29 | ||||
-rw-r--r-- | src/worker_main.c | 1 |
5 files changed, 81 insertions, 3 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2333a8..6476318 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,7 +29,8 @@ add_executable(worker worker_main.c worker.c git.c msg.c net.c - process.c) + process.c + signal.c) target_link_libraries(server PRIVATE pthread) target_link_libraries(worker PRIVATE git2 pthread) diff --git a/src/signal.c b/src/signal.c new file mode 100644 index 0000000..fc4ac8b --- /dev/null +++ b/src/signal.c @@ -0,0 +1,23 @@ +#include "signal.h" +#include "log.h" + +#include <pthread.h> +#include <signal.h> + +volatile sig_atomic_t global_stop_flag = 0; + +int signal_set_thread_attr(pthread_attr_t *attr) +{ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGQUIT); + sigaddset(&set, SIGTERM); + + if (pthread_attr_setsigmask_np(attr, &set)) { + print_errno("pthread_attr_setsigmask_np"); + return -1; + } + + return 0; +} diff --git a/src/signal.h b/src/signal.h new file mode 100644 index 0000000..ac6da9d --- /dev/null +++ b/src/signal.h @@ -0,0 +1,28 @@ +#ifndef __SIGNAL_H__ +#define __SIGNAL_H__ + +#include <pthread.h> +#include <signal.h> +#include <string.h> + +extern volatile sig_atomic_t global_stop_flag; + +static void signal_handler(int) +{ + global_stop_flag = 1; +} + +static __attribute__((constructor)) void signal_handler_install() +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); +} + +int signal_set_thread_attr(pthread_attr_t *attr); + +#endif diff --git a/src/worker.c b/src/worker.c index 0dc64d3..d26408f 100644 --- a/src/worker.c +++ b/src/worker.c @@ -5,6 +5,7 @@ #include "msg.h" #include "net.h" #include "process.h" +#include "signal.h" #include <errno.h> #include <pthread.h> @@ -45,6 +46,13 @@ git_shutdown: void worker_destroy(struct worker *worker) { + print_log("Shutting down\n"); + + if (worker->task_active) { + if (pthread_join(worker->task, NULL)) + print_errno("pthread_join"); + worker->task_active = 0; + } if (pthread_mutex_destroy(&worker->task_mtx)) print_errno("pthread_mutex_destroy"); close(worker->fd); @@ -141,6 +149,7 @@ static void *worker_task_wrapper(void *_ctx) static int worker_schedule_task(struct worker *worker, const struct msg *msg, worker_task_body body) { struct worker_task_context *ctx; + pthread_attr_t attr; int ret = 0; ctx = malloc(sizeof(*ctx)); @@ -156,15 +165,29 @@ static int worker_schedule_task(struct worker *worker, const struct msg *msg, wo goto free_ctx; } + ret = pthread_attr_init(&attr); + if (ret < 0) { + print_errno("pthread_attr_init"); + goto free_msg; + } + + ret = signal_set_thread_attr(&attr); + if (ret < 0) + goto free_attr; + ret = pthread_create(&worker->task, NULL, worker_task_wrapper, ctx); if (ret < 0) { print_errno("pthread_create"); - goto free_msg; + goto free_attr; } worker->task_active = 1; + pthread_attr_destroy(&attr); return ret; +free_attr: + pthread_attr_destroy(&attr); + free_msg: msg_free(ctx->msg); free(ctx->msg); @@ -245,11 +268,13 @@ int worker_main(struct worker *worker, int, char *[]) if (ret < 0) return ret; - while (1) { + while (!global_stop_flag) { print_log("Waiting for a new command\n"); ret = msg_recv_and_handle(worker->fd, worker_msg_handler_lock, worker); if (ret < 0) return ret; } + + return ret; } diff --git a/src/worker_main.c b/src/worker_main.c index d88071d..b5ccd51 100644 --- a/src/worker_main.c +++ b/src/worker_main.c @@ -1,4 +1,5 @@ #include "const.h" +#include "signal.h" #include "worker.h" #include <getopt.h> |