#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" #include "loglib.h" #include "auxlib.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 avlog_ilog(void *ptr, int loglevel, const char *fmt, va_list ap) { __vpilog(loglevel, NULL, fmt, ap); } static void setup(void) { log_init(); av_register_all(); avcodec_register_all(); avformat_network_init(); signals(); metafile_setup(); epoll_setup(); inotify_setup(); av_log_set_callback(avlog_ilog); openlog("rtpengine-recording", LOG_PID | LOG_NDELAY, LOG_DAEMON); } 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(); daemonize(); //wpidfile(); for (int i = 0; i < NUM_THREADS; i++) start_poller_thread(); wait_for_signal(); dbg("shutting down"); wait_threads_finish(); cleanup(); }