b3b539f46a97b93685143f6f701b2d7abd872c4e
[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
29 static inline void __socket_garbage_collector()
30 {
31         DIR *dp;
32         struct dirent *dentry;
33         char tmp[MAX_LOCAL_BUFSZ];
34
35         dp = opendir(AUL_SOCK_PREFIX);
36         if (dp == NULL)
37                 return;
38
39         while ((dentry = readdir(dp)) != NULL) {
40                 if (!isdigit(dentry->d_name[0]))
41                         continue;
42
43                 snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name);
44                 if (access(tmp, F_OK) < 0) {    /* Flawfinder: ignore */
45                         snprintf(tmp, MAX_LOCAL_BUFSZ, "%s/%s", AUL_SOCK_PREFIX,
46                                  dentry->d_name);
47                         unlink(tmp);
48                         continue;
49                 }
50         }
51         closedir(dp);
52 }
53
54 static inline int __send_app_dead_signal(int dead_pid)
55 {
56         DBusMessage *message;
57
58         if (bus == NULL)
59                 return -1;
60
61         message = dbus_message_new_signal(AUL_DBUS_PATH,
62                                           AUL_DBUS_SIGNAL_INTERFACE,
63                                           AUL_DBUS_APPDEAD_SIGNAL);
64
65         if (dbus_message_append_args(message,
66                                      DBUS_TYPE_UINT32, &dead_pid,
67                                      DBUS_TYPE_INVALID) == FALSE) {
68                 _E("Failed to load data error");
69                 return -1;
70         }
71
72         if (dbus_connection_send(bus, message, NULL) == FALSE) {
73                 _E("dbus send error");
74                 return -1;
75         }
76
77         dbus_connection_flush(bus);
78         dbus_message_unref(message);
79
80         _D("send dead signal done\n");
81
82         return 0;
83 }
84
85 static int __sigchild_action(void *data)
86 {
87         pid_t dead_pid;
88         char buf[MAX_LOCAL_BUFSZ];
89
90         dead_pid = (pid_t) data;
91         if (dead_pid <= 0)
92                 goto end;
93
94         __send_app_dead_signal(dead_pid);
95
96         snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, dead_pid);
97         unlink(buf);
98
99         __socket_garbage_collector();
100  end:
101         return 0;
102 }
103
104 static void __launchpad_sig_child(int signo, siginfo_t *info, void *data)
105 {
106         int status;
107         pid_t child_pid;
108         pthread_t thid;
109         pid_t child_pgid;
110
111         child_pgid = getpgid(info->si_pid);
112         _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid);
113
114         while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
115                 if (child_pid == child_pgid)
116                         killpg(child_pgid, SIGKILL);
117                 __sigchild_action((void *)child_pid);
118         }
119
120         return;
121 }
122
123 static inline int __signal_init(void)
124 {
125         int i;
126         for (i = 0; i < _NSIG; i++) {
127                 switch (i) {
128                         /* controlled by sys-assert package*/
129                 case SIGQUIT:
130                 case SIGILL:
131                 case SIGABRT:
132                 case SIGBUS:
133                 case SIGFPE:
134                 case SIGSEGV:
135                 case SIGPIPE:
136                         break;
137                 default:
138                         signal(i, SIG_DFL);
139                         break;
140                 }
141         }
142
143         return 0;
144 }
145
146 static inline int __signal_set_sigchld(void)
147 {
148         struct sigaction act;
149         DBusError error;
150
151         dbus_error_init(&error);
152         dbus_threads_init_default();
153         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
154         if (!bus) {
155                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
156                 dbus_error_free(&error);
157                 return -1;
158         }
159         /* TODO: if process stop mechanism is included, 
160         should be modified (SA_NOCLDSTOP)*/
161         act.sa_handler = NULL;
162         act.sa_sigaction = __launchpad_sig_child;
163         sigemptyset(&act.sa_mask);
164         act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
165
166         if (sigaction(SIGCHLD, &act, &old_sigchild) < 0)
167                 return -1;
168
169         return 0;
170 }
171
172 static inline int __signal_unset_sigchld(void)
173 {
174         struct sigaction dummy;
175
176         if (bus == NULL)
177                 return 0;
178
179         dbus_connection_close(bus);
180         if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0)
181                 return -1;
182
183         return 0;
184 }
185
186 static inline int __signal_fini(void)
187 {
188 #ifndef PRELOAD_ACTIVATE
189         int i;
190         for (i = 0; i < _NSIG; i++)
191                 signal(i, SIG_DFL);
192 #endif
193         return 0;
194 }
195