diff --git a/daemon/aux.c b/daemon/aux.c index 7ec7f73d8..b145c9dc3 100644 --- a/daemon/aux.c +++ b/daemon/aux.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "aux.h" @@ -15,6 +16,18 @@ + +struct detach_thread { + GThreadFunc func; + gpointer data; +}; + + +mutex_t threads_to_join_lock = MUTEX_STATIC_INIT; +static GSList *threads_to_join; + + + GList *g_list_link(GList *list, GList *el) { el->prev = NULL; el->next = list; @@ -102,3 +115,43 @@ void g_queue_clear(GQueue *q) { } #endif + + + +void thread_join_me() { + mutex_lock(&threads_to_join_lock); + threads_to_join = g_slist_prepend(threads_to_join, g_thread_self()); + mutex_unlock(&threads_to_join_lock); +} + +void threads_join_all() { + GThread *t; + + mutex_lock(&threads_to_join_lock); + while (threads_to_join) { + t = threads_to_join->data; + g_thread_join(t); + threads_to_join = g_slist_delete_link(threads_to_join, threads_to_join); + } + mutex_unlock(&threads_to_join_lock); +} + +static gpointer thread_detach_func(gpointer d) { + struct detach_thread *dt = d; + + dt->func(dt->data); + g_slice_free1(sizeof(*dt), dt); + thread_join_me(); + return NULL; +} + +void thread_create_detach(GThreadFunc f, gpointer d) { + struct detach_thread *dt; + + dt = g_slice_alloc(sizeof(*dt)); + dt->func = f; + dt->data = d; + + if (!g_thread_create(thread_detach_func, dt, TRUE, NULL)) + abort(); +} diff --git a/daemon/aux.h b/daemon/aux.h index 7f1d53538..08a94794e 100644 --- a/daemon/aux.h +++ b/daemon/aux.h @@ -156,6 +156,7 @@ typedef GCond *cond_t; #define mutex_lock(m) g_static_mutex_lock(m) #define mutex_trylock(m) g_static_mutex_trylock(m) #define mutex_unlock(m) g_static_mutex_unlock(m) +#define MUTEX_STATIC_INIT G_STATIC_MUTEX_INIT #define rwlock_init(l) g_static_rw_lock_init(l) #define rwlock_lock_r(l) g_static_rw_lock_reader_lock(l) @@ -178,6 +179,7 @@ typedef GCond cond_t; #define mutex_lock(m) g_mutex_lock(m) #define mutex_trylock(m) g_mutex_trylock(m) #define mutex_unlock(m) g_mutex_unlock(m) +#define MUTEX_STATIC_INIT {0} #define rwlock_init(l) g_rw_lock_init(l) #define rwlock_lock_r(l) g_rw_lock_reader_lock(l) @@ -194,4 +196,10 @@ typedef GCond cond_t; +void thread_join_me(); +void threads_join_all(); +void thread_create_detach(GThreadFunc, gpointer); + + + #endif diff --git a/daemon/main.c b/daemon/main.c index 45c7d27a5..05e7c3104 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -312,7 +312,6 @@ int main(int argc, char **argv) { int ret; void *dlh; const char **strp; - GThread *signal_handler_thread; options(&argc, &argv); g_thread_init(NULL); @@ -405,17 +404,16 @@ int main(int argc, char **argv) { die("Refusing to continue without working Redis database\n"); } - signal_handler_thread = g_thread_create(sighandler, NULL, TRUE, NULL); - if (!signal_handler_thread) - die("Failed to create thread\n"); + thread_create_detach(sighandler, NULL); while (!global_shutdown) { ret = poller_poll(p, 100); if (ret == -1) break; + threads_join_all(); } - g_thread_join(signal_handler_thread); + threads_join_all(); mylog(LOG_INFO, "Version %s shutting down", MEDIAPROXY_VERSION);