Fix build error
[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_errno.h>
36 #include <widget_provider.h>
37 #include <widget_conf.h>
38
39 #include "critical_log.h"
40 #include "main.h"
41 #include "debug.h"
42 #include "fault.h"
43 #include "client.h"
44 #include "util.h"
45 #include "conf.h"
46
47 static struct info {
48 #if defined(_USE_ECORE_TIME_GET)
49         double alarm_tv;
50 #else
51         struct timeval alarm_tv;
52 #endif
53         int marked;
54         int disable_checker;
55         struct sigaction SEGV_act;
56         struct sigaction ILL_act;
57         struct sigaction ALRM_act;
58         struct sigaction USR1_act;
59         struct sigaction ABRT_act;
60         char **argv;
61 } s_info = {
62         .marked = 0,
63         .disable_checker = 0,
64         .argv = NULL,
65 };
66
67 static void signal_handler(int signum, siginfo_t *info, void *unused)
68 {
69         char *so_fname;
70         char *symbol = NULL;
71
72         so_fname = util_get_current_module(&symbol);
73
74         if (info->si_signo == SIGALRM) {
75                 if (!s_info.marked) {
76                         DbgPrint("Ignore false alarm signal [false]\n");
77                         return;
78                 }
79
80 #if defined(_USE_ECORE_TIME_GET)
81                 double tv;
82                 tv = ecore_time_get();
83                 if (tv - s_info.alarm_tv < DEFAULT_LIFE_TIMER) {
84                         DbgPrint("Ignore false alarm signal [%lf]\n", tv - s_info.alarm_tv);
85                         return;
86                 }
87
88                 CRITICAL_LOG("ALARM: %lf (%d, %d)\n", tv - s_info.alarm_tv, DEFAULT_LIFE_TIMER, DEFAULT_LOAD_TIMER);
89 #else
90                 struct timeval tv;
91                 struct timeval res_tv;
92
93                 if (gettimeofday(&tv, NULL) < 0) {
94                         ErrPrint("gettimeofday: %d\n", errno);
95                         tv.tv_sec = 0;
96                         tv.tv_usec = 0;
97                 }
98
99                 timersub(&tv, &s_info.alarm_tv, &res_tv);
100
101                 /*!
102                  * \note
103                  *      GAP: 1 sec
104                  */
105                 if (res_tv.tv_sec < DEFAULT_LIFE_TIMER) {
106                         DbgPrint("Ignore false alarm signal [%d]\n", res_tv.tv_sec);
107                         return;
108                 }
109
110                 CRITICAL_LOG("ALARM: %d.%d (%d, %d)\n",
111                                 res_tv.tv_sec, res_tv.tv_usec, DEFAULT_LIFE_TIMER, DEFAULT_LOAD_TIMER);
112 #endif
113         } else if (so_fname) {
114                 int fd;
115                 char log_fname[256];
116
117                 snprintf(log_fname, sizeof(log_fname), "%s/slave.%d", WIDGET_CONF_LOG_PATH, getpid());
118                 fd = open(log_fname, O_WRONLY|O_CREAT|O_SYNC, 0644);
119                 if (fd >= 0) {
120                         if (write(fd, so_fname, strlen(so_fname)) != strlen(so_fname)) {
121                                 ErrPrint("Failed to recording the fault SO filename (%s)\n", so_fname);
122                         }
123                         if (close(fd) < 0) {
124                                 ErrPrint("close: %d\n", errno);
125                         }
126                 }
127         }
128
129         CRITICAL_LOG("SIGNAL> Received from PID[%d]\n", info->si_pid);
130         CRITICAL_LOG("SIGNAL> Signal: %d (%d)\n", signum, info->si_signo);
131         CRITICAL_LOG("SIGNAL> Error code: %d\n", info->si_code);
132         CRITICAL_LOG("SIGNAL> Address: %p\n", info->si_addr);
133         CRITICAL_LOG("Package: [%s] Symbol[%s]\n", so_fname, symbol);
134
135         if (so_fname) {
136                 int len = strlen(s_info.argv[0]);
137                 memset(s_info.argv[0], 0, len);
138                 strncpy(s_info.argv[0], util_basename(so_fname), len - 1);
139                 free(so_fname);
140         } else {
141                 CRITICAL_LOG("Unable to find a so_fname (%s)\n", symbol);
142         }
143
144         free(symbol);
145
146         switch (signum) {
147         case SIGSEGV:
148                 s_info.SEGV_act.sa_sigaction(signum, info, unused);
149                 break;
150         case SIGALRM:
151                 s_info.ALRM_act.sa_sigaction(signum, info, unused);
152                 break;
153         case SIGABRT:
154                 s_info.ABRT_act.sa_sigaction(signum, info, unused);
155                 break;
156         case SIGILL:
157                 s_info.ILL_act.sa_sigaction(signum, info, unused);
158                 break;
159         case SIGUSR1:
160                 s_info.USR1_act.sa_sigaction(signum, info, unused);
161                 break;
162         default:
163                 ErrPrint("Unhandled signal\n");
164                 break;
165         }
166 }
167
168 HAPI int fault_init(char **argv)
169 {
170         struct sigaction act;
171         char *ecore_abort;
172
173         s_info.argv = argv;
174
175         act.sa_sigaction = signal_handler;
176         act.sa_flags = SA_SIGINFO;
177
178         if (sigemptyset(&act.sa_mask) != 0) {
179                 ErrPrint("Failed to init signal: %d\n", errno);
180         }
181
182         if (sigaddset(&act.sa_mask, SIGUSR1) != 0) {
183                 ErrPrint("Failed to add set: %d\n", errno);
184         }
185
186         if (sigaddset(&act.sa_mask, SIGALRM) != 0) {
187                 ErrPrint("Failed to add set: %d\n", errno);
188         }
189
190         ecore_abort = getenv("ECORE_ERROR_ABORT");
191         if (!ecore_abort || ecore_abort[0] != '1') {
192                 if (sigaddset(&act.sa_mask, SIGSEGV) != 0) {
193                         ErrPrint("Failed to add set: %d\n", errno);
194                 }
195                 if (sigaddset(&act.sa_mask, SIGABRT) != 0) {
196                         ErrPrint("Failed to add set: %d\n", errno);
197                 }
198                 if (sigaddset(&act.sa_mask, SIGILL) != 0) {
199                         ErrPrint("Failed to add set: %d\n", errno);
200                 }
201
202                 if (sigaction(SIGSEGV, &act, &s_info.SEGV_act) < 0) {
203                         ErrPrint("Failed to install the SEGV handler\n");
204                 }
205
206                 if (sigaction(SIGABRT, &act, &s_info.ABRT_act) < 0) {
207                         ErrPrint("Faield to install the ABRT handler\n");
208                 }
209
210                 if (sigaction(SIGILL, &act, &s_info.ILL_act) < 0) {
211                         ErrPrint("Faield to install the ILL handler\n");
212                 }
213         }
214
215         if (sigaction(SIGUSR1, &act, &s_info.USR1_act) < 0) {
216                 ErrPrint("Failed to install the USR1 handler\n");
217         }
218
219         if (sigaction(SIGALRM, &act, &s_info.ALRM_act) < 0) {
220                 ErrPrint("Failed to install the ALRM handler\n");
221         }
222
223         return 0;
224 }
225
226 HAPI int fault_fini(void)
227 {
228         /*!
229          * \todo
230          * remove all signal handlers
231          */
232         return 0;
233 }
234
235 HAPI int fault_mark_call(const char *pkgname, const char *filename, const char *funcname, int noalarm, int life_time)
236 {
237         if (!s_info.disable_checker) {
238                 widget_provider_send_call(pkgname, filename, funcname);
239         }
240         /*!
241          * \NOTE
242          *   To use this "alarm", the widget have to do not use the 'sleep' series functions.
243          *   because those functions will generate alarm signal.
244          *   then the module will be deactivated
245          *
246          *   Enable alarm for detecting infinite loop
247          */
248         if (!noalarm) {
249 #if defined(_USE_ECORE_TIME_GET)
250                 s_info.alarm_tv = ecore_time_get();
251 #else
252                 if (gettimeofday(&s_info.alarm_tv, NULL) < 0) {
253                         ErrPrint("gettimeofday: %d\n", errno);
254                         s_info.alarm_tv.tv_sec = 0;
255                         s_info.alarm_tv.tv_usec = 0;
256                 }
257 #endif
258                 s_info.marked = 1;
259                 alarm(life_time);
260         }
261
262         return 0;
263 }
264
265 HAPI int fault_unmark_call(const char *pkgname, const char *filename, const char *funcname, int noalarm)
266 {
267         if (!noalarm) {
268                 /*!
269                  * \NOTE
270                  * Disable alarm
271                  */
272                 alarm(0);
273                 s_info.marked = 0;
274         }
275
276         if (!s_info.disable_checker) {
277                 widget_provider_send_ret(pkgname, filename, funcname);
278         }
279         return 0;
280 }
281
282 HAPI void fault_disable_call_option(void)
283 {
284         s_info.disable_checker = 1;
285 }
286
287 /* End of a file */