added LICENSE, NOTICE files and rpmlint warning fix
[framework/appfw/debug-launchpad.git] / src / sigchild.h
1 /*
2  *  debug-launchpad
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jungmin Cho <chivalry.cho@samsung.com>, Gwangho Hwang <gwang.hwang@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         child_pgid = getpgid(info->si_pid);
143         _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid);
144
145         while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
146                 if (child_pid == child_pgid)
147                         killpg(child_pgid, SIGKILL);
148                 __sigchild_action((void *)child_pid);
149         }
150
151         return;
152 }
153
154 static inline int __signal_init(void)
155 {
156         int i;
157         for (i = 0; i < _NSIG; i++) {
158                 switch (i) {
159                         /* controlled by sys-assert package*/
160                 case SIGQUIT:
161                 case SIGILL:
162                 case SIGABRT:
163                 case SIGBUS:
164                 case SIGFPE:
165                 case SIGSEGV:
166                 case SIGPIPE:
167                         break;
168                 default:
169                         signal(i, SIG_DFL);
170                         break;
171                 }
172         }
173
174         return 0;
175 }
176
177 static inline int __signal_set_sigchld(void)
178 {
179         struct sigaction act;
180         DBusError error;
181
182         dbus_error_init(&error);
183         dbus_threads_init_default();
184         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
185         if (!bus) {
186                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
187                 dbus_error_free(&error);
188                 return -1;
189         }
190         /* TODO: if process stop mechanism is included, 
191         should be modified (SA_NOCLDSTOP)*/
192         act.sa_handler = NULL;
193         act.sa_sigaction = __launchpad_sig_child;
194         sigemptyset(&act.sa_mask);
195         act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
196
197         if (sigaction(SIGCHLD, &act, &old_sigchild) < 0)
198                 return -1;
199
200         return 0;
201 }
202
203 static inline int __signal_unset_sigchld(void)
204 {
205         struct sigaction dummy;
206
207         if (bus == NULL)
208                 return 0;
209
210         dbus_connection_close(bus);
211         if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0)
212                 return -1;
213
214         return 0;
215 }
216
217 static inline int __signal_block_sigchld(void)
218 {
219         sigset_t newmask;
220
221         sigemptyset(&newmask);
222         sigaddset(&newmask, SIGCHLD);
223
224         if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
225                 _E("SIG_BLOCK error");
226                 return -1;
227         }
228
229         _D("SIGCHLD blocked");
230
231         return 0;
232 }
233
234 static inline int __signal_unblock_sigchld(void)
235 {
236         if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
237                 _E("SIG_SETMASK error");
238                 return -1;
239         }
240
241         _D("SIGCHLD unblocked");
242         return 0;
243 }
244
245 static inline int __signal_fini(void)
246 {
247 #ifndef PRELOAD_ACTIVATE
248         int i;
249         for (i = 0; i < _NSIG; i++)
250                 signal(i, SIG_DFL);
251 #endif
252         return 0;
253 }
254