tizen 2.3 release
[framework/appfw/aul-1.git] / 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         int ret;
121
122         dead_pid = (pid_t) data;
123         _I("dead_pid(%d)", dead_pid);
124         if (dead_pid <= 0)
125                 goto end;
126
127         ret = __send_app_dead_signal(dead_pid);
128
129         _I("__send_app_dead_signal(%d)", ret);
130
131  end:
132         return 0;
133 }
134
135 static void __launchpad_sig_child(int signo, siginfo_t *info, void *data)
136 {
137         int status;
138         pid_t child_pid;
139         pid_t child_pgid;
140
141         child_pgid = getpgid(info->si_pid);
142         _I("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         _I("after __sigchild_action");
151
152         return;
153 }
154
155 static inline int __signal_init(void)
156 {
157         int i;
158         for (i = 0; i < _NSIG; i++) {
159                 switch (i) {
160                         /* controlled by sys-assert package*/
161                 case SIGQUIT:
162                 case SIGILL:
163                 case SIGABRT:
164                 case SIGBUS:
165                 case SIGFPE:
166                 case SIGSEGV:
167                 case SIGPIPE:
168                         break;
169                 default:
170                         signal(i, SIG_DFL);
171                         break;
172                 }
173         }
174
175         return 0;
176 }
177
178 static inline int __signal_set_sigchld(void)
179 {
180         struct sigaction act;
181         DBusError error;
182
183         dbus_error_init(&error);
184         dbus_threads_init_default();
185         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
186         if (!bus) {
187                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
188                 dbus_error_free(&error);
189                 return -1;
190         }
191         /* TODO: if process stop mechanism is included,
192         should be modified (SA_NOCLDSTOP)*/
193         act.sa_handler = NULL;
194         act.sa_sigaction = __launchpad_sig_child;
195         sigemptyset(&act.sa_mask);
196         act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
197
198         if (sigaction(SIGCHLD, &act, &old_sigchild) < 0)
199                 return -1;
200
201         return 0;
202 }
203
204 static inline int __signal_unset_sigchld(void)
205 {
206         struct sigaction dummy;
207
208         if (bus == NULL)
209                 return 0;
210
211         dbus_connection_close(bus);
212         if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0)
213                 return -1;
214
215         return 0;
216 }
217
218 static inline int __signal_block_sigchld(void)
219 {
220         sigset_t newmask;
221
222         sigemptyset(&newmask);
223         sigaddset(&newmask, SIGCHLD);
224
225         if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
226                 _E("SIG_BLOCK error");
227                 return -1;
228         }
229
230         _D("SIGCHLD blocked");
231
232         return 0;
233 }
234
235 static inline int __signal_unblock_sigchld(void)
236 {
237         if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
238                 _E("SIG_SETMASK error");
239                 return -1;
240         }
241
242         _D("SIGCHLD unblocked");
243         return 0;
244 }
245
246 static inline int __signal_fini(void)
247 {
248 #ifndef PRELOAD_ACTIVATE
249         int i;
250         for (i = 0; i < _NSIG; i++)
251                 signal(i, SIG_DFL);
252 #endif
253         return 0;
254 }
255