From 08d827fd00d95c704fa9a975164952c76ecd9c13 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 20 May 2024 15:51:45 +0200 Subject: [PATCH] broadcast_should_exit: fixed signalling Since the function can be called from the signal handler, there must not be any call to signal unsafe function (see signal-safety(7)). Actually, this is not just a fix of a possible problem but it caused activelly problems within the reflector when 2 signals were raised one shortly after anotner. Was stuck at following (snippet): ``` std::unique_lock::unique_lock(std::mutex&) at /usr/include/c++/14.1.1/bits/unique_lock.h:74 (inlined by) state_root::broadcast_should_exit() at /home/martin/Projects/ultragrid/src/host.cpp:533 exit_uv at /home/martin/Projects/ultragrid/src/host.cpp:587 signal_handler(int) at /home/martin/Projects/ultragrid/src/hd-rum-translator/hd-rum-translator.cpp:219 ``` --- src/host.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/host.cpp b/src/host.cpp index fce0c920a..997ebe68f 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -507,7 +507,7 @@ struct state_root { unique_lock lk(lock); should_exit_callbacks.clear(); lk.unlock(); - broadcast_should_exit(); // here just exit the should exit thr + broadcast_should_exit(true); // here just exit the should exit thr should_exit_thread.join(); for (int i = 0; i < 2; ++i) { platform_pipe_close(should_exit_pipe[0]); @@ -519,33 +519,36 @@ struct state_root { static void should_exit_watcher(state_root *s) { set_thread_name(__func__); - char c; - while (PLATFORM_PIPE_READ(s->should_exit_pipe[0], &c, 1) != 1) { - perror("PLATFORM_PIPE_READ"); - } - unique_lock lk(s->lock); - for (auto const &c : s->should_exit_callbacks) { - get<0>(c)(get<1>(c)); + char q = 0; + bool should_exit_thread_notified = false; + while (q != QUIT_WATCHER_FLAG) { + while (PLATFORM_PIPE_READ(s->should_exit_pipe[0], &q, + 1) != 1) { + perror("PLATFORM_PIPE_READ"); + } + if (!should_exit_thread_notified) { + unique_lock lk(s->lock); + for (auto const &c : s->should_exit_callbacks) { + get<0>(c)(get<1>(c)); + } + should_exit_thread_notified = true; + } } } - void broadcast_should_exit() { - char c = 0; - unique_lock lk(lock); - if (should_exit_thread_notified) { - return; - } - should_exit_thread_notified = true; - while (PLATFORM_PIPE_WRITE(should_exit_pipe[1], &c, 1) != 1) { + void broadcast_should_exit(bool quit_watcher = false) + { + const char q = quit_watcher ? QUIT_WATCHER_FLAG : 0; + while (PLATFORM_PIPE_WRITE(should_exit_pipe[1], &q, 1) != 1) { perror("PLATFORM_PIPE_WRITE"); } } volatile int exit_status = EXIT_SUCCESS; private: + static constexpr char QUIT_WATCHER_FLAG = 1; mutex lock; fd_t should_exit_pipe[2]; thread should_exit_thread; - bool should_exit_thread_notified{false}; list> should_exit_callbacks; friend void register_should_exit_callback(struct module *mod, void (*callback)(void *),