Make struct signal_task generic and make afs use it.
[paraslash.git] / afs.c
diff --git a/afs.c b/afs.c
index 5ccb17f..71a9f1c 100644 (file)
--- a/afs.c
+++ b/afs.c
 #include "afs.h"
 #include "ipc.h"
 #include "string.h"
+#include "list.h"
+#include "sched.h"
+#include "signal.h"
+#include "fd.h"
 
 /** \file afs.c Paraslash's audio file selector. */
 
@@ -481,19 +485,78 @@ static void setup_command_socket(void)
                command_socket);
 }
 
-int server_socket;
+static int server_socket;
 
-void shed(void)
+void loop(void)
 {
        for (;;)
                sleep(1);
 }
 
+static void afs_shutdown(enum osl_close_flags flags)
+{
+       PARA_NOTICE_LOG("cleaning up\n");
+       score_shutdown(flags);
+       attribute_shutdown(flags);
+       mood_close();
+       playlist_close();
+       moods_shutdown(flags);
+       playlists_shutdown(flags);
+       lyrics_shutdown(flags);
+       images_shutdown(flags);
+       aft_shutdown(flags);
+}
+
+static void signal_pre_select(struct sched *s, struct task *t)
+{
+       struct signal_task *st = t->private_data;
+       t->ret = 1;
+       para_fd_set(st->fd, &s->rfds, &s->max_fileno);
+}
+
+static void signal_post_select(struct sched *s, struct task *t)
+{
+       struct signal_task *st = t->private_data;
+       t->ret = 1;
+       if (!FD_ISSET(st->fd, &s->rfds))
+               return;
+       st->signum = para_next_signal();
+       PARA_NOTICE_LOG("caught signal %d\n", st->signum);
+       t->ret = 1;
+       if (st->signum == SIGUSR1)
+               return; /* ignore SIGUSR1 */
+       afs_shutdown(OSL_MARK_CLEAN);
+       t->ret = -E_SIGNAL_CAUGHT;
+}
+
+static void register_signal_task(void)
+{
+       static struct signal_task signal_task_struct;
+       struct signal_task *st = &signal_task_struct;
+       st->fd = para_signal_init();
+       PARA_INFO_LOG("signal pipe: fd %d\n", st->fd);
+       para_install_sighandler(SIGINT);
+       para_install_sighandler(SIGTERM);
+       para_install_sighandler(SIGPIPE);
+
+       st->task.pre_select = signal_pre_select;
+       st->task.post_select = signal_post_select;
+       st->task.private_data = st;
+       sprintf(st->task.status, "signal task");
+       register_task(&st->task);
+}
+
+void register_tasks(void)
+{
+       register_signal_task();
+}
+
 __noreturn int afs_init(uint32_t cookie, int socket_fd)
 {
        int ret;
 //     void *shm_area;
        enum play_mode current_play_mode;
+       struct sched s;
 
        server_socket = socket_fd;
        socket_cookie = cookie;
@@ -524,7 +587,10 @@ __noreturn int afs_init(uint32_t cookie, int socket_fd)
                goto aft_init_error;
 
        current_play_mode = init_admissible_files();
-       shed();
+       register_tasks();
+       s.default_timeout.tv_sec = 0;
+       s.default_timeout.tv_usec = 99 * 1000;
+       sched(&s);
 
 #if 0
        ret = shm_new(sizeof(struct callback_data));
@@ -788,19 +854,6 @@ out:
        mutex_unlock(result_mutex); /* wake up child */
 }
 
-static void afs_shutdown(enum osl_close_flags flags)
-{
-       score_shutdown(flags);
-       attribute_shutdown(flags);
-       mood_close();
-       playlist_close();
-       moods_shutdown(flags);
-       playlists_shutdown(flags);
-       lyrics_shutdown(flags);
-       images_shutdown(flags);
-       aft_shutdown(flags);
-}
-
 #if 0
 static int got_sigchld;
 static void server_loop(int child_pid)