Signals: only one thread needed now
[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 *SigThread (void *);
35
36 vlc_module_begin ();
37     set_shortname (N_("Signals"));
38     set_category (CAT_INTERFACE);
39     set_subcategory (SUBCAT_INTERFACE_CONTROL);
40     set_description (N_("POSIX signals handling interface"));
41     set_capability ("interface", 0);
42     set_callbacks (Open, Close);
43 vlc_module_end ();
44
45 struct intf_sys_t
46 {
47     vlc_thread_t    thread;
48     int             signum;
49 };
50
51 static int Open (vlc_object_t *obj)
52 {
53     intf_thread_t *intf = (intf_thread_t *)obj;
54     intf_sys_t *p_sys = malloc (sizeof (*p_sys));
55
56     if (p_sys == NULL)
57         return VLC_ENOMEM;
58
59     p_sys->signum = 0;
60     intf->p_sys = p_sys;
61
62     if (vlc_clone (&p_sys->thread, SigThread, obj, VLC_THREAD_PRIORITY_LOW))
63     {
64         free (p_sys);
65         intf->p_sys = NULL;
66         return VLC_ENOMEM;
67     }
68
69     intf->pf_run = NULL;
70     return 0;
71 }
72
73 static void Close (vlc_object_t *obj)
74 {
75     intf_thread_t *intf = (intf_thread_t *)obj;
76     intf_sys_t *p_sys = intf->p_sys;
77
78     vlc_cancel (p_sys->thread);
79 #ifdef __APPLE__
80    /* In Mac OS X up to 10.5 sigwait (among others) is not a pthread
81     * cancellation point, so we throw a dummy quit signal to end
82     * sigwait() in the sigth thread */
83     pthread_kill (p_sys->thread, SIGQUIT);
84 # endif
85     vlc_join (p_sys->thread, NULL);
86     free (p_sys);
87 }
88
89 static void *SigThread (void *data)
90 {
91     intf_thread_t *obj = data;
92     intf_sys_t *p_sys = obj->p_sys;
93     sigset_t set;
94
95     sigemptyset (&set);
96     sigaddset (&set, SIGHUP);
97     sigaddset (&set, SIGINT);
98     sigaddset (&set, SIGQUIT);
99     sigaddset (&set, SIGTERM);
100
101     sigaddset (&set, SIGCHLD);
102
103     for (;;)
104     {
105         int signum;
106
107         sigwait (&set, &signum);
108
109 #ifdef __APPLE__
110         /* In Mac OS X up to 10.5 sigwait (among others) is not a pthread
111          * cancellation point */
112         vlc_testcancel();
113 #endif
114
115         switch (signum)
116         {
117             case SIGINT:
118             case SIGHUP:
119             case SIGTERM:
120             case SIGQUIT:
121                 msg_Err (obj, "Caught %s signal, exiting...",
122                          strsignal (p_sys->signum));
123                 vlc_object_kill (obj->p_libvlc);
124                 break;
125         }
126     }
127 }