#include "main.h" #include #include #include #include #include #include #include #include #include #include "log.h" #include "epoll.h" #include "inotify.h" #include "metafile.h" #include "garbage.h" static GQueue threads = G_QUEUE_INIT; // only accessed from main thread volatile int shutdown_flag; static void signals(void) { sigset_t ss; sigfillset(&ss); sigdelset(&ss, SIGABRT); sigdelset(&ss, SIGSEGV); sigdelset(&ss, SIGQUIT); sigprocmask(SIG_SETMASK, &ss, NULL); pthread_sigmask(SIG_SETMASK, &ss, NULL); } static void setup(void) { av_register_all(); avcodec_register_all(); avformat_network_init(); signals(); metafile_setup(); epoll_setup(); inotify_setup(); } static void start_poller_thread(void) { pthread_t *thr = g_slice_alloc(sizeof(*thr)); int ret = pthread_create(thr, NULL, poller_thread, GUINT_TO_POINTER(garbage_new_thread_num())); if (ret) die_errno("pthread_create failed"); g_queue_push_tail(&threads, thr); } static void wait_threads_finish(void) { pthread_t *thr; while ((thr = g_queue_pop_head(&threads))) { pthread_cancel(*thr); pthread_join(*thr, NULL); g_slice_free1(sizeof(*thr), thr); } } static void wait_for_signal(void) { sigset_t ss; int ret, sig; sigemptyset(&ss); sigaddset(&ss, SIGINT); sigaddset(&ss, SIGTERM); while (1) { ret = sigwait(&ss, &sig); if (ret == -1) { if (errno == EAGAIN || errno == EINTR) continue; abort(); } shutdown_flag = 1; break; } } static void cleanup(void) { garbage_collect_all(); metafile_cleanup(); inotify_cleanup(); epoll_cleanup(); } int main() { setup(); for (int i = 0; i < NUM_THREADS; i++) start_poller_thread(); wait_for_signal(); dbg("shutting down"); wait_threads_finish(); cleanup(); }