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