signals: use the VLC thread API
[vlc.git] / modules / control / signals.c
1 /*****************************************************************************
2  * signals.c : signals handler module for vlc
3  *****************************************************************************
4  * Copyright (C) 2008 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <signal.h>
26 #include <time.h>
27
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_interface.h>
31
32 static int  Open (vlc_object_t *);
33 static void Close (vlc_object_t *);
34 static void Run (intf_thread_t *);
35 static void *SigThread (void *);
36
37 vlc_module_begin ();
38     set_shortname (N_("Signals"));
39     set_category (CAT_INTERFACE);
40     set_subcategory (SUBCAT_INTERFACE_CONTROL);
41     set_description (N_("POSIX signals handling interface"));
42     set_capability ("interface", 0);
43     set_callbacks (Open, Close);
44 vlc_module_end ();
45
46 struct intf_sys_t
47 {
48     vlc_thread_t    thread;
49     int             signum;
50 };
51
52 static int Open (vlc_object_t *obj)
53 {
54     intf_thread_t *intf = (intf_thread_t *)obj;
55     intf_sys_t *p_sys = malloc (sizeof (*p_sys));
56
57     if (p_sys == NULL)
58         return VLC_ENOMEM;
59
60     p_sys->signum = 0;
61     intf->p_sys = p_sys;
62
63     if (vlc_clone (&p_sys->thread, SigThread, obj, VLC_THREAD_PRIORITY_LOW))
64     {
65         free (p_sys);
66         intf->p_sys = NULL;
67         return VLC_ENOMEM;
68     }
69
70     intf->pf_run = Run;
71     return 0;
72 }
73
74 static void Close (vlc_object_t *obj)
75 {
76     intf_thread_t *intf = (intf_thread_t *)obj;
77     intf_sys_t *p_sys = intf->p_sys;
78
79     vlc_cancel (p_sys->thread);
80 #ifdef __APPLE__
81    /* In Mac OS X up to 10.5 sigwait (among others) is not a pthread
82     * cancellation point, so we throw a dummy quit signal to end
83     * sigwait() in the sigth thread */
84     pthread_kill (p_sys->thread, SIGQUIT);
85 # endif
86     vlc_join (p_sys->thread, NULL);
87     free (p_sys);
88 }
89
90 static void *SigThread (void *data)
91 {
92     intf_thread_t *obj = data;
93     intf_sys_t *p_sys = obj->p_sys;
94     sigset_t set;
95
96     sigemptyset (&set);
97     sigaddset (&set, SIGHUP);
98     sigaddset (&set, SIGINT);
99     sigaddset (&set, SIGQUIT);
100     sigaddset (&set, SIGTERM);
101
102     sigaddset (&set, SIGCHLD);
103
104     for (;;)
105     {
106         int signum;
107
108         sigwait (&set, &signum);
109
110 #ifdef __APPLE__
111         /* In Mac OS X up to 10.5 sigwait (among others) is not a pthread
112          * cancellation point */
113         vlc_testcancel();
114 #endif
115
116         vlc_object_lock (obj);
117         p_sys->signum = signum;
118         vlc_object_signal_unlocked (obj);
119         vlc_object_unlock (obj);
120     }
121 }
122
123 static void Run (intf_thread_t *obj)
124 {
125     intf_sys_t *p_sys = obj->p_sys;
126
127     vlc_object_lock (obj);
128     while (vlc_object_alive (obj))
129     {
130         switch (p_sys->signum)
131         {
132             case SIGINT:
133             case SIGHUP:
134             case SIGTERM:
135             case SIGQUIT:
136                 msg_Err (obj, "Caught %s signal, exiting...",
137                          strsignal (p_sys->signum));
138                 goto out;
139         }
140         vlc_object_wait (obj);
141     }
142
143 out:
144     vlc_object_unlock (obj);
145     vlc_object_kill (obj->p_libvlc);
146 }