aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2022-08-26 05:51:53 +0200
committerEgor Tensin <Egor.Tensin@gmail.com>2022-08-26 05:54:22 +0200
commit1de2aaa4001eb2d0ddfc4f86ab2c2a3eebdc9841 (patch)
tree85b0290fd51c220a9a621e98c0b88d92ce776e33
parentworker: capture process output (diff)
downloadcimple-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.txt3
-rw-r--r--src/signal.c23
-rw-r--r--src/signal.h28
-rw-r--r--src/worker.c29
-rw-r--r--src/worker_main.c1
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>