fixed smack define related build error
[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 <sys/smack.h>
25 #include "app_signal.h"
26
27 static struct sigaction old_sigchild;
28 static DBusConnection *bus = NULL;
29 sigset_t oldmask;
30 static int gdbserver_pid;
31 static int gdbserver_app_pid;
32
33 static inline void __socket_garbage_collector()
34 {
35         DIR *dp;
36         struct dirent *dentry;
37         char tmp[MAX_LOCAL_BUFSZ];
38
39         dp = opendir(AUL_SOCK_PREFIX);
40         if (dp == NULL)
41                 return;
42
43         while ((dentry = readdir(dp)) != NULL) {
44                 if (!isdigit(dentry->d_name[0]))
45                         continue;
46
47                 snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name);
48                 if (access(tmp, F_OK) < 0) {    /* Flawfinder: ignore */
49                         snprintf(tmp, MAX_LOCAL_BUFSZ, "%s/%s", AUL_SOCK_PREFIX,
50                                  dentry->d_name);
51                         unlink(tmp);
52                         continue;
53                 }
54         }
55         closedir(dp);
56 }
57
58 static inline int __send_app_dead_signal(int dead_pid)
59 {
60         DBusMessage *message;
61
62         if (bus == NULL)
63                 return -1;
64
65         message = dbus_message_new_signal(AUL_DBUS_PATH,
66                                           AUL_DBUS_SIGNAL_INTERFACE,
67                                           AUL_DBUS_APPDEAD_SIGNAL);
68
69         if (dbus_message_append_args(message,
70                                      DBUS_TYPE_UINT32, &dead_pid,
71                                      DBUS_TYPE_INVALID) == FALSE) {
72                 _E("Failed to load data error");
73                 return -1;
74         }
75
76         if (dbus_connection_send(bus, message, NULL) == FALSE) {
77                 _E("dbus send error");
78                 return -1;
79         }
80
81         dbus_connection_flush(bus);
82         dbus_message_unref(message);
83
84         _D("send dead signal done\n");
85
86         return 0;
87 }
88
89 static inline int __send_app_launch_signal(int launch_pid)
90 {
91         DBusMessage *message;
92
93         if (bus == NULL)
94                 return -1;
95
96         message = dbus_message_new_signal(AUL_DBUS_PATH,
97                                           AUL_DBUS_SIGNAL_INTERFACE,
98                                           AUL_DBUS_APPLAUNCH_SIGNAL);
99
100         if (dbus_message_append_args(message,
101                                      DBUS_TYPE_UINT32, &launch_pid,
102                                      DBUS_TYPE_INVALID) == FALSE) {
103                 _E("Failed to load data error");
104                 return -1;
105         }
106
107         if (dbus_connection_send(bus, message, NULL) == FALSE) {
108                 _E("dbus send error");
109                 return -1;
110         }
111
112         dbus_connection_flush(bus);
113         dbus_message_unref(message);
114
115         _D("send launch signal done\n");
116
117         return 0;
118 }
119
120 /* chmod and chsmack to read file without root privilege */
121 static void __chmod_chsmack_toread(const char * path)
122 {
123         /* chmod */
124         if(dlp_chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0))
125         {
126                 _E("unable to set 644 to %s", path);
127         }else{
128                 _D("set 644 to %s", path);
129         }
130
131         /* chsmack */
132         if(smack_setlabel(path, "*", SMACK_LABEL_ACCESS))
133         {
134                 _E("failed chsmack -a \"*\" %s", path);
135         }else{
136                 _D("chsmack -a \"*\" %s", path);
137         }
138
139         return;
140 }
141
142 static int __sigchild_action(void *data)
143 {
144         pid_t dead_pid;
145         char buf[MAX_LOCAL_BUFSZ];
146
147         dead_pid = (pid_t) data;
148         if (dead_pid <= 0)
149                 goto end;
150
151         /* send app pid instead of gdbserver pid */
152         if(dead_pid == gdbserver_pid)
153                 dead_pid = gdbserver_app_pid;
154
155         /* valgrind xml file */
156         if(access(PATH_VALGRIND_XMLFILE,F_OK)==0)
157         {
158                 __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE);
159         }
160
161         __send_app_dead_signal(dead_pid);
162
163         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, dead_pid);
164         unlink(buf);
165
166         __socket_garbage_collector();
167  end:
168         return 0;
169 }
170
171 static void __launchpad_sig_child(int signo, siginfo_t *info, void *data)
172 {
173         int status;
174         pid_t child_pid;
175         pid_t child_pgid;
176
177         child_pgid = getpgid(info->si_pid);
178         _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid);
179
180         while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
181                 if (child_pid == child_pgid)
182                         killpg(child_pgid, SIGKILL);
183                 __sigchild_action((void *)child_pid);
184         }
185
186         return;
187 }
188
189 static inline int __signal_init(void)
190 {
191         int i;
192         for (i = 0; i < _NSIG; i++) {
193                 switch (i) {
194                         /* controlled by sys-assert package*/
195                 case SIGQUIT:
196                 case SIGILL:
197                 case SIGABRT:
198                 case SIGBUS:
199                 case SIGFPE:
200                 case SIGSEGV:
201                 case SIGPIPE:
202                         break;
203                 default:
204                         signal(i, SIG_DFL);
205                         break;
206                 }
207         }
208
209         return 0;
210 }
211
212 static inline int __signal_set_sigchld(void)
213 {
214         struct sigaction act;
215         DBusError error;
216
217         dbus_error_init(&error);
218         dbus_threads_init_default();
219         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
220         if (!bus) {
221                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
222                 dbus_error_free(&error);
223                 return -1;
224         }
225         /* TODO: if process stop mechanism is included, 
226         should be modified (SA_NOCLDSTOP)*/
227         act.sa_handler = NULL;
228         act.sa_sigaction = __launchpad_sig_child;
229         sigemptyset(&act.sa_mask);
230         act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
231
232         if (sigaction(SIGCHLD, &act, &old_sigchild) < 0)
233                 return -1;
234
235         return 0;
236 }
237
238 static inline int __signal_unset_sigchld(void)
239 {
240         struct sigaction dummy;
241
242         if (bus == NULL)
243                 return 0;
244
245         dbus_connection_close(bus);
246         if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0)
247                 return -1;
248
249         return 0;
250 }
251
252 static inline int __signal_block_sigchld(void)
253 {
254         sigset_t newmask;
255
256         sigemptyset(&newmask);
257         sigaddset(&newmask, SIGCHLD);
258
259         if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
260                 _E("SIG_BLOCK error");
261                 return -1;
262         }
263
264         _D("SIGCHLD blocked");
265
266         return 0;
267 }
268
269 static inline int __signal_unblock_sigchld(void)
270 {
271         if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
272                 _E("SIG_SETMASK error");
273                 return -1;
274         }
275
276         _D("SIGCHLD unblocked");
277         return 0;
278 }
279
280 static inline int __signal_fini(void)
281 {
282 #ifndef PRELOAD_ACTIVATE
283         int i;
284         for (i = 0; i < _NSIG; i++)
285                 signal(i, SIG_DFL);
286 #endif
287         return 0;
288 }
289