sycn with master
[platform/framework/web/data-provider-slave.git] / src / fault.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (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://www.tizenopensource.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
34 #include <provider.h>
35
36 #include "critical_log.h"
37 #include "main.h"
38 #include "debug.h"
39 #include "fault.h"
40 #include "conf.h"
41 #include "client.h"
42 #include "util.h"
43
44 static struct info {
45         struct timeval alarm_tv;
46         int marked;
47         int disable_checker;
48 } s_info = {
49         .marked = 0,
50         .disable_checker = 0,
51 };
52
53 static void signal_handler(int signum, siginfo_t *info, void *unused)
54 {
55         char *so_fname;
56         char *symbol = NULL;
57
58         so_fname = util_get_current_module(&symbol);
59
60         if (info->si_signo == SIGALRM) {
61                 struct timeval tv;
62                 struct timeval res_tv;
63
64                 if (!s_info.marked) {
65                         DbgPrint("Ignore false alarm signal [false]\n");
66                         return;
67                 }
68
69                 gettimeofday(&tv, NULL);
70
71                 timersub(&tv, &s_info.alarm_tv, &res_tv);
72
73                 /*!
74                  * \note
75                  *      GAP: 1 sec
76                  */
77                 if (res_tv.tv_sec < DEFAULT_LIFE_TIMER) {
78                         DbgPrint("Ignore false alarm signal [%d]\n", res_tv.tv_sec);
79                         return;
80                 }
81
82                 DbgPrint("ALARM: %d.%d (%d, %d)\n",
83                                 res_tv.tv_sec, res_tv.tv_usec, DEFAULT_LIFE_TIMER, DEFAULT_LOAD_TIMER);
84         } else if (so_fname) {
85                 int fd;
86                 char log_fname[256];
87
88                 snprintf(log_fname, sizeof(log_fname), "%s/slave.%d", SLAVE_LOG_PATH, getpid());
89                 fd = open(log_fname, O_WRONLY|O_CREAT|O_SYNC, 0644);
90                 if (fd >= 0) {
91                         if (write(fd, so_fname, strlen(so_fname)) != strlen(so_fname))
92                                 ErrPrint("Failed to recording the fault SO filename (%s)\n", so_fname);
93                         close(fd);
94                 }
95         }
96
97         ErrPrint("=====\n");
98         ErrPrint("SIGNAL> Received from PID[%d]\n", info->si_pid);
99         ErrPrint("SIGNAL> Signal: %d (%d)\n", signum, info->si_signo);
100         ErrPrint("SIGNAL> Error code: %d\n", info->si_code);
101         ErrPrint("SIGNAL> Address: %p\n", info->si_addr);
102         ErrPrint("Package: [%s] Symbol[%s]\n", so_fname, symbol);
103         free(so_fname);
104         free(symbol);
105
106         _exit(0);
107         return;
108 }
109
110 HAPI int fault_init(void)
111 {
112         struct sigaction act;
113
114         if (access("/tmp/live.err", F_OK) == 0)
115                 ErrPrint("Error log still exists (/tmp/live.err)\n");
116
117         act.sa_sigaction = signal_handler;
118         act.sa_flags = SA_SIGINFO;
119
120         sigemptyset(&act.sa_mask);
121         sigaddset(&act.sa_mask, SIGSEGV);
122         sigaddset(&act.sa_mask, SIGABRT);
123         sigaddset(&act.sa_mask, SIGILL);
124         sigaddset(&act.sa_mask, SIGUSR1);
125         sigaddset(&act.sa_mask, SIGALRM);
126
127         if (sigaction(SIGSEGV, &act, NULL) < 0)
128                 ErrPrint("Failed to install the SEGV handler\n");
129
130         if (sigaction(SIGABRT, &act, NULL) < 0)
131                 ErrPrint("Faield to install the ABRT handler\n");
132
133         if (sigaction(SIGILL, &act, NULL) < 0)
134                 ErrPrint("Faield to install the ILL handler\n");
135
136         if (sigaction(SIGUSR1, &act, NULL) < 0)
137                 ErrPrint("Failed to install the USR1 handler\n");
138
139         if (sigaction(SIGALRM, &act, NULL) < 0)
140                 ErrPrint("Failed to install the ALRM handler\n");
141
142         return 0;
143 }
144
145 HAPI int fault_fini(void)
146 {
147         /*!
148          * \todo
149          * remove all signal handlers
150          */
151         return 0;
152 }
153
154 HAPI int fault_mark_call(const char *pkgname, const char *filename, const char *funcname, int noalarm, int life_time)
155 {
156         if (!s_info.disable_checker)
157                 provider_send_call(pkgname, filename, funcname);
158         /*!
159          * \NOTE
160          *   To use this "alarm", the livebox have to do not use the 'sleep' series functions.
161          *   because those functions will generate alarm signal.
162          *   then the module will be deactivated
163          *
164          *   Enable alarm for detecting infinite loop
165          */
166         if (!noalarm) {
167                 gettimeofday(&s_info.alarm_tv, NULL);
168                 s_info.marked = 1;
169                 alarm(life_time);
170         }
171
172         return 0;
173 }
174
175 HAPI int fault_unmark_call(const char *pkgname, const char *filename, const char *funcname, int noalarm)
176 {
177         if (!noalarm) {
178                 /*!
179                  * \NOTE
180                  * Disable alarm
181                  */
182                 alarm(0);
183                 s_info.marked = 0;
184         }
185
186         if (!s_info.disable_checker)
187                 provider_send_ret(pkgname, filename, funcname);
188         return 0;
189 }
190
191 HAPI void fault_disable_call_option(void)
192 {
193         s_info.disable_checker = 1;
194 }
195
196 /* End of a file */