dcfbe1e1121ef7a747866baaffb4f1c23cb98408
[platform/core/appfw/data-provider-slave.git] / src / fault.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18 #include <stdio.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <dlfcn.h>
22 #include <sys/time.h>
23 #include <execinfo.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30
31 #include <dlog.h>
32 #include <Eina.h>
33 #include <Ecore.h>
34
35 #include <widget_provider.h>
36 #include <widget_conf.h>
37
38 #include "critical_log.h"
39 #include "main.h"
40 #include "debug.h"
41 #include "fault.h"
42 #include "client.h"
43 #include "util.h"
44 #include "conf.h"
45
46 static struct info {
47 #if defined(_USE_ECORE_TIME_GET)
48         double alarm_tv;
49 #else
50         struct timeval alarm_tv;
51 #endif
52         int marked;
53         int disable_checker;
54         struct sigaction SEGV_act;
55         struct sigaction ILL_act;
56         struct sigaction ALRM_act;
57         struct sigaction USR1_act;
58         struct sigaction ABRT_act;
59         char **argv;
60 } s_info = {
61         .marked = 0,
62         .disable_checker = 0,
63         .argv = NULL,
64 };
65
66 static void signal_handler(int signum, siginfo_t *info, void *unused)
67 {
68         char *so_fname;
69         char *symbol = NULL;
70
71         so_fname = util_get_current_module(&symbol);
72
73         if (info->si_signo == SIGALRM) {
74                 if (!s_info.marked) {
75                         DbgPrint("Ignore false alarm signal [false]\n");
76                         return;
77                 }
78
79 #if defined(_USE_ECORE_TIME_GET)
80                 double tv;
81                 tv = ecore_time_get();
82                 if (tv - s_info.alarm_tv < DEFAULT_LIFE_TIMER) {
83                         DbgPrint("Ignore false alarm signal [%lf]\n", tv - s_info.alarm_tv);
84                         return;
85                 }
86
87                 CRITICAL_LOG("ALARM: %lf (%d, %d)\n", tv - s_info.alarm_tv, DEFAULT_LIFE_TIMER, DEFAULT_LOAD_TIMER);
88 #else
89                 struct timeval tv;
90                 struct timeval res_tv;
91
92                 if (gettimeofday(&tv, NULL) < 0) {
93                         ErrPrint("gettimeofday: %d\n", errno);
94                         tv.tv_sec = 0;
95                         tv.tv_usec = 0;
96                 }
97
98                 timersub(&tv, &s_info.alarm_tv, &res_tv);
99
100                 /*!
101                  * \note
102                  *      GAP: 1 sec
103                  */
104                 if (res_tv.tv_sec < DEFAULT_LIFE_TIMER) {
105                         DbgPrint("Ignore false alarm signal [%d]\n", res_tv.tv_sec);
106                         return;
107                 }
108
109                 CRITICAL_LOG("ALARM: %d.%d (%d, %d)\n",
110                                 res_tv.tv_sec, res_tv.tv_usec, DEFAULT_LIFE_TIMER, DEFAULT_LOAD_TIMER);
111 #endif
112         } else if (so_fname) {
113                 int fd;
114                 char log_fname[256];
115
116                 snprintf(log_fname, sizeof(log_fname), "%s/slave.%d", WIDGET_CONF_LOG_PATH, getpid());
117                 fd = open(log_fname, O_WRONLY|O_CREAT|O_SYNC, 0644);
118                 if (fd >= 0) {
119                         if (write(fd, so_fname, strlen(so_fname)) != strlen(so_fname)) {
120                                 ErrPrint("Failed to recording the fault SO filename (%s)\n", so_fname);
121                         }
122                         if (close(fd) < 0) {
123                                 ErrPrint("close: %d\n", errno);
124                         }
125                 }
126         }
127
128         CRITICAL_LOG("SIGNAL> Received from PID[%d]\n", info->si_pid);
129         CRITICAL_LOG("SIGNAL> Signal: %d (%d)\n", signum, info->si_signo);
130         CRITICAL_LOG("SIGNAL> Error code: %d\n", info->si_code);
131         CRITICAL_LOG("SIGNAL> Address: %p\n", info->si_addr);
132         CRITICAL_LOG("Package: [%s] Symbol[%s]\n", so_fname, symbol);
133
134         if (so_fname) {
135                 int len = strlen(s_info.argv[0]);
136                 memset(s_info.argv[0], 0, len);
137                 strncpy(s_info.argv[0], util_basename(so_fname), len - 1);
138                 free(so_fname);
139         } else {
140                 CRITICAL_LOG("Unable to find a so_fname (%s)\n", symbol);
141         }
142
143         free(symbol);
144
145         switch (signum) {
146         case SIGSEGV:
147                 s_info.SEGV_act.sa_sigaction(signum, info, unused);
148                 break;
149         case SIGALRM:
150                 s_info.ALRM_act.sa_sigaction(signum, info, unused);
151                 break;
152         case SIGABRT:
153                 s_info.ABRT_act.sa_sigaction(signum, info, unused);
154                 break;
155         case SIGILL:
156                 s_info.ILL_act.sa_sigaction(signum, info, unused);
157                 break;
158         case SIGUSR1:
159                 s_info.USR1_act.sa_sigaction(signum, info, unused);
160                 break;
161         default:
162                 ErrPrint("Unhandled signal\n");
163                 break;
164         }
165 }
166
167 HAPI int fault_init(char **argv)
168 {
169         struct sigaction act;
170         char *ecore_abort;
171
172         s_info.argv = argv;
173
174         act.sa_sigaction = signal_handler;
175         act.sa_flags = SA_SIGINFO;
176
177         if (sigemptyset(&act.sa_mask) != 0) {
178                 ErrPrint("Failed to init signal: %d\n", errno);
179         }
180
181         if (sigaddset(&act.sa_mask, SIGUSR1) != 0) {
182                 ErrPrint("Failed to add set: %d\n", errno);
183         }
184
185         if (sigaddset(&act.sa_mask, SIGALRM) != 0) {
186                 ErrPrint("Failed to add set: %d\n", errno);
187         }
188
189         ecore_abort = getenv("ECORE_ERROR_ABORT");
190         if (!ecore_abort || ecore_abort[0] != '1') {
191                 if (sigaddset(&act.sa_mask, SIGSEGV) != 0) {
192                         ErrPrint("Failed to add set: %d\n", errno);
193                 }
194                 if (sigaddset(&act.sa_mask, SIGABRT) != 0) {
195                         ErrPrint("Failed to add set: %d\n", errno);
196                 }
197                 if (sigaddset(&act.sa_mask, SIGILL) != 0) {
198                         ErrPrint("Failed to add set: %d\n", errno);
199                 }
200
201                 if (sigaction(SIGSEGV, &act, &s_info.SEGV_act) < 0) {
202                         ErrPrint("Failed to install the SEGV handler\n");
203                 }
204
205                 if (sigaction(SIGABRT, &act, &s_info.ABRT_act) < 0) {
206                         ErrPrint("Faield to install the ABRT handler\n");
207                 }
208
209                 if (sigaction(SIGILL, &act, &s_info.ILL_act) < 0) {
210                         ErrPrint("Faield to install the ILL handler\n");
211                 }
212         }
213
214         if (sigaction(SIGUSR1, &act, &s_info.USR1_act) < 0) {
215                 ErrPrint("Failed to install the USR1 handler\n");
216         }
217
218         if (sigaction(SIGALRM, &act, &s_info.ALRM_act) < 0) {
219                 ErrPrint("Failed to install the ALRM handler\n");
220         }
221
222         return 0;
223 }
224
225 HAPI int fault_fini(void)
226 {
227         /*!
228          * \todo
229          * remove all signal handlers
230          */
231         return 0;
232 }
233
234 HAPI int fault_mark_call(const char *pkgname, const char *filename, const char *funcname, int noalarm, int life_time)
235 {
236         if (!s_info.disable_checker) {
237                 widget_provider_send_call(pkgname, filename, funcname);
238         }
239         /*!
240          * \NOTE
241          *   To use this "alarm", the widget have to do not use the 'sleep' series functions.
242          *   because those functions will generate alarm signal.
243          *   then the module will be deactivated
244          *
245          *   Enable alarm for detecting infinite loop
246          */
247         if (!noalarm) {
248 #if defined(_USE_ECORE_TIME_GET)
249                 s_info.alarm_tv = ecore_time_get();
250 #else
251                 if (gettimeofday(&s_info.alarm_tv, NULL) < 0) {
252                         ErrPrint("gettimeofday: %d\n", errno);
253                         s_info.alarm_tv.tv_sec = 0;
254                         s_info.alarm_tv.tv_usec = 0;
255                 }
256 #endif
257                 s_info.marked = 1;
258                 alarm(life_time);
259         }
260
261         return 0;
262 }
263
264 HAPI int fault_unmark_call(const char *pkgname, const char *filename, const char *funcname, int noalarm)
265 {
266         if (!noalarm) {
267                 /*!
268                  * \NOTE
269                  * Disable alarm
270                  */
271                 alarm(0);
272                 s_info.marked = 0;
273         }
274
275         if (!s_info.disable_checker) {
276                 widget_provider_send_ret(pkgname, filename, funcname);
277         }
278         return 0;
279 }
280
281 HAPI void fault_disable_call_option(void)
282 {
283         s_info.disable_checker = 1;
284 }
285
286 /* End of a file */