Tizen 2.4 SDK Rev6 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 <sys/signalfd.h>
25 #include <signal.h>
26 #include "app_signal.h"
27
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         DBusConnection *bus;
58         DBusMessage *message;
59         DBusError error;
60
61         dbus_error_init(&error);
62         dbus_threads_init_default();
63         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
64         if (!bus) {
65                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
66                 dbus_error_free(&error);
67                 return -1;
68         }
69
70         message = dbus_message_new_signal(AUL_DBUS_PATH,
71                                           AUL_DBUS_SIGNAL_INTERFACE,
72                                           AUL_DBUS_APPDEAD_SIGNAL);
73
74         if (dbus_message_append_args(message,
75                                      DBUS_TYPE_UINT32, &dead_pid,
76                                      DBUS_TYPE_INVALID) == FALSE) {
77                 _E("Failed to load data error");
78                 return -1;
79         }
80
81         if (dbus_connection_send(bus, message, NULL) == FALSE) {
82                 _E("dbus send error");
83                 return -1;
84         }
85
86         dbus_connection_flush(bus);
87         dbus_connection_close(bus);
88         dbus_message_unref(message);
89
90         _D("send dead signal done\n");
91
92         return 0;
93 }
94
95 static inline int __send_app_launch_signal(int launch_pid)
96 {
97         DBusConnection *bus;
98         DBusMessage *message;
99         DBusError error;
100
101         dbus_error_init(&error);
102         dbus_threads_init_default();
103         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
104         if (!bus) {
105                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
106                 dbus_error_free(&error);
107                 return -1;
108         }
109
110         message = dbus_message_new_signal(AUL_DBUS_PATH,
111                                           AUL_DBUS_SIGNAL_INTERFACE,
112                                           AUL_DBUS_APPLAUNCH_SIGNAL);
113
114         if (dbus_message_append_args(message,
115                                      DBUS_TYPE_UINT32, &launch_pid,
116                                      DBUS_TYPE_INVALID) == FALSE) {
117                 _E("Failed to load data error");
118                 return -1;
119         }
120
121         if (dbus_connection_send(bus, message, NULL) == FALSE) {
122                 _E("dbus send error");
123                 return -1;
124         }
125
126         dbus_connection_flush(bus);
127         dbus_connection_close(bus);
128         dbus_message_unref(message);
129
130         _D("send launch signal done\n");
131
132         return 0;
133 }
134
135 static int __sigchild_action(void *data)
136 {
137         pid_t dead_pid;
138         int ret;
139
140         dead_pid = (pid_t) data;
141         _I("dead_pid(%d)", dead_pid);
142         if (dead_pid <= 0)
143                 goto end;
144
145         ret = __send_app_dead_signal(dead_pid);
146
147         _I("__send_app_dead_signal(%d)", ret);
148
149  end:
150         return 0;
151 }
152
153 static void __launchpad_process_sigchld(struct signalfd_siginfo *info)
154 {
155         int status;
156         pid_t child_pid;
157         pid_t child_pgid;
158
159         child_pgid = getpgid(info->ssi_pid);
160         _I("dead_pid = %d pgid = %d", info->ssi_pid, child_pgid);
161
162         while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
163                 if (child_pid == child_pgid)
164                         killpg(child_pgid, SIGKILL);
165                 __sigchild_action((void *)child_pid);
166         }
167
168         _I("after __sigchild_action");
169
170         return;
171 }
172
173 static inline int __signal_init(void)
174 {
175         int i;
176         for (i = 0; i < _NSIG; i++) {
177                 switch (i) {
178                         /* controlled by sys-assert package*/
179                 case SIGQUIT:
180                 case SIGILL:
181                 case SIGABRT:
182                 case SIGBUS:
183                 case SIGFPE:
184                 case SIGSEGV:
185                 case SIGPIPE:
186                         break;
187                 default:
188                         signal(i, SIG_DFL);
189                         break;
190                 }
191         }
192
193         return 0;
194 }
195
196 static inline int __signal_get_sigchld_fd(void)
197 {
198         sigset_t mask;
199         int sfd;
200
201         sigemptyset(&mask);
202         sigaddset(&mask, SIGCHLD);
203
204         if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1)
205                 _E("failed to sigprocmask");
206
207         sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
208         if (sfd == -1) {
209                 _E("failed to create signalfd for SIGCHLD");
210                 return -1;
211         }
212
213         return sfd;
214 }
215
216 static inline int __signal_unblock_sigchld(void)
217 {
218         if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
219                 _E("SIG_SETMASK error");
220                 return -1;
221         }
222
223         _D("SIGCHLD unblocked");
224         return 0;
225 }
226
227 static inline int __signal_fini(void)
228 {
229 #ifndef PRELOAD_ACTIVATE
230         int i;
231         for (i = 0; i < _NSIG; i++)
232                 signal(i, SIG_DFL);
233 #endif
234         return 0;
235 }
236