Source code formating unification
[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 #include <pthread.h>
18 #include "app_signal.h"
19
20 static struct sigaction old_sigchild;
21 static DBusConnection *bus = NULL;
22 sigset_t oldmask;
23
24 static inline void __socket_garbage_collector()
25 {
26     DIR *dp;
27     struct dirent *dentry;
28     char tmp[MAX_LOCAL_BUFSZ];
29
30     dp = opendir(AUL_SOCK_PREFIX);
31     if (dp == NULL) {
32         return;
33     }
34
35     while ((dentry = readdir(dp)) != NULL) {
36         if (!isdigit(dentry->d_name[0])) {
37             continue;
38         }
39
40         snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name);
41         if (access(tmp, F_OK) < 0) {            /* Flawfinder: ignore */
42             snprintf(tmp, MAX_LOCAL_BUFSZ, "%s/%s", AUL_SOCK_PREFIX,
43                      dentry->d_name);
44             unlink(tmp);
45             continue;
46         }
47     }
48     closedir(dp);
49 }
50
51 static inline int __send_app_dead_signal(int dead_pid)
52 {
53     DBusMessage *message;
54
55     if (bus == NULL) {
56         return -1;
57     }
58
59     message = dbus_message_new_signal(AUL_DBUS_PATH,
60                                       AUL_DBUS_SIGNAL_INTERFACE,
61                                       AUL_DBUS_APPDEAD_SIGNAL);
62
63     if (dbus_message_append_args(message,
64                                  DBUS_TYPE_UINT32, &dead_pid,
65                                  DBUS_TYPE_INVALID) == FALSE)
66     {
67         _E("Failed to load data error");
68         return -1;
69     }
70
71     if (dbus_connection_send(bus, message, NULL) == FALSE) {
72         _E("dbus send error");
73         return -1;
74     }
75
76     dbus_connection_flush(bus);
77     dbus_message_unref(message);
78
79     _D("send dead signal done\n");
80
81     return 0;
82 }
83
84 static inline int __send_app_launch_signal(int launch_pid)
85 {
86     DBusMessage *message;
87
88     if (bus == NULL) {
89         return -1;
90     }
91
92     message = dbus_message_new_signal(AUL_DBUS_PATH,
93                                       AUL_DBUS_SIGNAL_INTERFACE,
94                                       AUL_DBUS_APPLAUNCH_SIGNAL);
95
96     if (dbus_message_append_args(message,
97                                  DBUS_TYPE_UINT32, &launch_pid,
98                                  DBUS_TYPE_INVALID) == FALSE)
99     {
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
127     __send_app_dead_signal(dead_pid);
128
129     snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, dead_pid);
130     unlink(buf);
131
132     __socket_garbage_collector();
133 end:
134     return 0;
135 }
136
137 static void __launchpad_sig_child(int signo, siginfo_t *info, void *data)
138 {
139     int status;
140     pid_t child_pid;
141     pid_t child_pgid;
142
143     // warning: unused parameter
144     signo = signo;
145     data = data;
146
147     child_pgid = getpgid(info->si_pid);
148     _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid);
149
150     while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
151         if (child_pid == child_pgid) {
152             killpg(child_pgid, SIGKILL);
153         }
154         __sigchild_action((void *)child_pid);
155     }
156
157     return;
158 }
159
160 static inline int __signal_init(void)
161 {
162     int i;
163     for (i = 0; i < _NSIG; i++) {
164         switch (i) {
165         /* controlled by sys-assert package*/
166         case SIGQUIT:
167         case SIGILL:
168         case SIGABRT:
169         case SIGBUS:
170         case SIGFPE:
171         case SIGSEGV:
172         case SIGPIPE:
173             break;
174         default:
175             signal(i, SIG_DFL);
176             break;
177         }
178     }
179
180     return 0;
181 }
182
183 static inline int __signal_set_sigchld(void)
184 {
185     struct sigaction act;
186     DBusError error;
187
188     dbus_error_init(&error);
189     dbus_threads_init_default();
190     bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
191     if (!bus) {
192         _E("Failed to connect to the D-BUS daemon: %s", error.message);
193         dbus_error_free(&error);
194         return -1;
195     }
196     /* TODO: if process stop mechanism is included,
197      * should be modified (SA_NOCLDSTOP)*/
198     act.sa_handler = NULL;
199     act.sa_sigaction = __launchpad_sig_child;
200     sigemptyset(&act.sa_mask);
201     act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
202
203     if (sigaction(SIGCHLD, &act, &old_sigchild) < 0) {
204         return -1;
205     }
206
207     return 0;
208 }
209
210 static inline int __signal_unset_sigchld(void)
211 {
212     struct sigaction dummy;
213
214     if (bus == NULL) {
215         return 0;
216     }
217
218     dbus_connection_close(bus);
219     if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0) {
220         return -1;
221     }
222
223     return 0;
224 }
225
226 static inline int __signal_block_sigchld(void)
227 {
228     sigset_t newmask;
229
230     sigemptyset(&newmask);
231     sigaddset(&newmask, SIGCHLD);
232
233     if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
234         _E("SIG_BLOCK error");
235         return -1;
236     }
237
238     _D("SIGCHLD blocked");
239
240     return 0;
241 }
242
243 static inline int __signal_unblock_sigchld(void)
244 {
245     if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
246         _E("SIG_SETMASK error");
247         return -1;
248     }
249
250     _D("SIGCHLD unblocked");
251     return 0;
252 }
253
254 static inline int __signal_fini(void)
255 {
256 #ifndef PRELOAD_ACTIVATE
257     int i;
258     for (i = 0; i < _NSIG; i++) {
259         signal(i, SIG_DFL);
260     }
261 #endif
262     return 0;
263 }
264