b9d35fb5ec62017fc0e7bc37e2c2c73d7c34ac1a
[platform/framework/web/wrt.git] / src / wrt-launchpad-daemon / launchpad_src / sigchild.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17
18 #include <pthread.h>
19 #include "app_signal.h"
20
21 static struct sigaction old_sigchild;
22 static DBusConnection *bus = NULL;
23 sigset_t oldmask;
24
25 static inline void __socket_garbage_collector()
26 {
27         DIR *dp;
28         struct dirent *dentry;
29         char tmp[MAX_LOCAL_BUFSZ];
30
31         dp = opendir(AUL_SOCK_PREFIX);
32         if (dp == NULL)
33                 return;
34
35         while ((dentry = readdir(dp)) != NULL) {
36                 if (!isdigit(dentry->d_name[0]))
37                         continue;
38
39                 snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name);
40                 if (access(tmp, F_OK) < 0) {    /* Flawfinder: ignore */
41                         snprintf(tmp, MAX_LOCAL_BUFSZ, "%s/%s", AUL_SOCK_PREFIX,
42                                  dentry->d_name);
43                         unlink(tmp);
44                         continue;
45                 }
46         }
47         closedir(dp);
48 }
49
50 static inline int __send_app_dead_signal(int dead_pid)
51 {
52         DBusMessage *message;
53
54         if (bus == NULL)
55                 return -1;
56
57         message = dbus_message_new_signal(AUL_DBUS_PATH,
58                                           AUL_DBUS_SIGNAL_INTERFACE,
59                                           AUL_DBUS_APPDEAD_SIGNAL);
60
61         if (dbus_message_append_args(message,
62                                      DBUS_TYPE_UINT32, &dead_pid,
63                                      DBUS_TYPE_INVALID) == FALSE) {
64                 _E("Failed to load data error");
65                 return -1;
66         }
67
68         if (dbus_connection_send(bus, message, NULL) == FALSE) {
69                 _E("dbus send error");
70                 return -1;
71         }
72
73         dbus_connection_flush(bus);
74         dbus_message_unref(message);
75
76         _D("send dead signal done\n");
77
78         return 0;
79 }
80
81 static inline int __send_app_launch_signal(int launch_pid)
82 {
83         DBusMessage *message;
84
85         if (bus == NULL)
86                 return -1;
87
88         message = dbus_message_new_signal(AUL_DBUS_PATH,
89                                           AUL_DBUS_SIGNAL_INTERFACE,
90                                           AUL_DBUS_APPLAUNCH_SIGNAL);
91
92         if (dbus_message_append_args(message,
93                                      DBUS_TYPE_UINT32, &launch_pid,
94                                      DBUS_TYPE_INVALID) == FALSE) {
95                 _E("Failed to load data error");
96                 return -1;
97         }
98
99         if (dbus_connection_send(bus, message, NULL) == FALSE) {
100                 _E("dbus send error");
101                 return -1;
102         }
103
104         dbus_connection_flush(bus);
105         dbus_message_unref(message);
106
107         _D("send launch signal done\n");
108
109         return 0;
110 }
111
112 static int __sigchild_action(void *data)
113 {
114         pid_t dead_pid;
115         char buf[MAX_LOCAL_BUFSZ];
116
117         dead_pid = (pid_t) data;
118         if (dead_pid <= 0)
119                 goto end;
120
121         __send_app_dead_signal(dead_pid);
122
123         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, dead_pid);
124         unlink(buf);
125
126         __socket_garbage_collector();
127  end:
128         return 0;
129 }
130
131 static void __launchpad_sig_child(int signo, siginfo_t *info, void *data)
132 {
133         int status;
134         pid_t child_pid;
135         pid_t child_pgid;
136
137         // warning: unused parameter
138         signo = signo;
139         data = data;
140
141         child_pgid = getpgid(info->si_pid);
142         _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid);
143
144         while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
145                 if (child_pid == child_pgid)
146                         killpg(child_pgid, SIGKILL);
147                 __sigchild_action((void *)child_pid);
148         }
149
150         return;
151 }
152
153 static inline int __signal_init(void)
154 {
155         int i;
156         for (i = 0; i < _NSIG; i++) {
157                 switch (i) {
158                         /* controlled by sys-assert package*/
159                 case SIGQUIT:
160                 case SIGILL:
161                 case SIGABRT:
162                 case SIGBUS:
163                 case SIGFPE:
164                 case SIGSEGV:
165                 case SIGPIPE:
166                         break;
167                 default:
168                         signal(i, SIG_DFL);
169                         break;
170                 }
171         }
172
173         return 0;
174 }
175
176 static inline int __signal_set_sigchld(void)
177 {
178         struct sigaction act;
179         DBusError error;
180
181         dbus_error_init(&error);
182         dbus_threads_init_default();
183         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
184         if (!bus) {
185                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
186                 dbus_error_free(&error);
187                 return -1;
188         }
189         /* TODO: if process stop mechanism is included, 
190         should be modified (SA_NOCLDSTOP)*/
191         act.sa_handler = NULL;
192         act.sa_sigaction = __launchpad_sig_child;
193         sigemptyset(&act.sa_mask);
194         act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
195
196         if (sigaction(SIGCHLD, &act, &old_sigchild) < 0)
197                 return -1;
198
199         return 0;
200 }
201
202 static inline int __signal_unset_sigchld(void)
203 {
204         struct sigaction dummy;
205
206         if (bus == NULL)
207                 return 0;
208
209         dbus_connection_close(bus);
210         if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0)
211                 return -1;
212
213         return 0;
214 }
215
216 static inline int __signal_block_sigchld(void)
217 {
218         sigset_t newmask;
219
220         sigemptyset(&newmask);
221         sigaddset(&newmask, SIGCHLD);
222
223         if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
224                 _E("SIG_BLOCK error");
225                 return -1;
226         }
227
228         _D("SIGCHLD blocked");
229
230         return 0;
231 }
232
233 static inline int __signal_unblock_sigchld(void)
234 {
235         if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
236                 _E("SIG_SETMASK error");
237                 return -1;
238         }
239
240         _D("SIGCHLD unblocked");
241         return 0;
242 }
243
244 static inline int __signal_fini(void)
245 {
246 #ifndef PRELOAD_ACTIVATE
247         int i;
248         for (i = 0; i < _NSIG; i++)
249                 signal(i, SIG_DFL);
250 #endif
251         return 0;
252 }
253