Logging intefaces in objects deleted
[profile/tv/apps/native/screen-reader.git] / src / main.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
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 #include <time.h>
18 #include <signal.h>
19 #include <err.h>
20 #include <execinfo.h>
21 #include <appcore-efl.h>
22 #include <Elementary.h>
23 #include <eldbus-1/Eldbus.h>
24 #include "navigator.h"
25 #include "window_tracker.h"
26 #include "logger.h"
27 #include "screen_reader.h"
28 #include "screen_reader_gestures.h"
29 #include "screen_reader_switch.h"
30
31 #define MAX_STACK_FRAMES 64
32 static void *stack_traces[MAX_STACK_FRAMES];
33
34 void posix_print_stack_trace(FILE *log_file)
35 {
36     int i, trace_size = 0;
37     char **messages = (char **)NULL;
38
39     trace_size = backtrace(stack_traces, MAX_STACK_FRAMES);
40     messages = backtrace_symbols(stack_traces, trace_size);
41
42     /* skip the first couple stack frames (as they are this function and
43      our handler) and also skip the last frame as it's (always?) junk. */
44     // for (i = 3; i < (trace_size - 1); ++i)
45     for (i = 0; i < trace_size; ++i) // we'll use this for now so you can see what's going on
46     {
47         fprintf(log_file, "  BACKTRACE LINE %i: %s\n",i, messages[i]);
48     }
49     if (messages) { free(messages); }
50 }
51
52 void print_warning(int sig, siginfo_t *siginfo, FILE *log_file)
53 {
54     switch(sig)
55     {
56     case SIGSEGV:
57         fputs("Caught SIGSEGV: Segmentation Fault\n", log_file);
58         break;
59     case SIGINT:
60         fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", log_file);
61         break;
62     case SIGFPE:
63         switch(siginfo->si_code)
64         {
65         case FPE_INTDIV:
66             fputs("Caught SIGFPE: (integer divide by zero)\n", log_file);
67             break;
68         case FPE_INTOVF:
69             fputs("Caught SIGFPE: (integer overflow)\n", log_file);
70             break;
71         case FPE_FLTDIV:
72             fputs("Caught SIGFPE: (floating-point divide by zero)\n", log_file);
73             break;
74         case FPE_FLTOVF:
75             fputs("Caught SIGFPE: (floating-point overflow)\n", log_file);
76             break;
77         case FPE_FLTUND:
78             fputs("Caught SIGFPE: (floating-point underflow)\n", log_file);
79             break;
80         case FPE_FLTRES:
81             fputs("Caught SIGFPE: (floating-point inexact result)\n", log_file);
82             break;
83         case FPE_FLTINV:
84             fputs("Caught SIGFPE: (floating-point invalid operation)\n", log_file);
85             break;
86         case FPE_FLTSUB:
87             fputs("Caught SIGFPE: (subscript out of range)\n", log_file);
88             break;
89         default:
90             fputs("Caught SIGFPE: Arithmetic Exception\n", log_file);
91             break;
92         }
93         break;
94     case SIGILL:
95         switch(siginfo->si_code)
96         {
97         case ILL_ILLOPC:
98             fputs("Caught SIGILL: (illegal opcode)\n", log_file);
99             break;
100         case ILL_ILLOPN:
101             fputs("Caught SIGILL: (illegal operand)\n", log_file);
102             break;
103         case ILL_ILLADR:
104             fputs("Caught SIGILL: (illegal addressing mode)\n", log_file);
105             break;
106         case ILL_ILLTRP:
107             fputs("Caught SIGILL: (illegal trap)\n", log_file);
108             break;
109         case ILL_PRVOPC:
110             fputs("Caught SIGILL: (privileged opcode)\n", log_file);
111             break;
112         case ILL_PRVREG:
113             fputs("Caught SIGILL: (privileged register)\n", log_file);
114             break;
115         case ILL_COPROC:
116             fputs("Caught SIGILL: (coprocessor error)\n", log_file);
117             break;
118         case ILL_BADSTK:
119             fputs("Caught SIGILL: (internal stack error)\n", log_file);
120             break;
121         default:
122             fputs("Caught SIGILL: Illegal Instruction\n", log_file);
123             break;
124         }
125         break;
126     case SIGTERM:
127         fputs("Caught SIGTERM: a termination request was sent to the program\n", log_file);
128         break;
129     case SIGABRT:
130         fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", log_file);
131         break;
132     default:
133         break;
134     }
135 }
136
137
138 void posix_signal_handler(int sig, siginfo_t *siginfo, void *context)
139 {
140     char file_name[256] = {0};
141     struct tm * timeinfo;
142     time_t rawtime = time(NULL);
143     timeinfo = localtime(&rawtime);
144     if (timeinfo)
145       sprintf(file_name, "/tmp/screen_reader_crash_stacktrace_%i%i%i_%i:%i:%i_pid_%i.log", timeinfo->tm_year,
146               timeinfo->tm_mon, timeinfo->tm_mday,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, getpid());
147     else
148       sprintf(file_name, "/tmp/screen_reader_crash_stacktrace_pid_%i.log", getpid());
149
150     FILE * log_file = fopen(file_name, "w");
151     if (log_file)
152       {
153          (void)context;
154          print_warning(sig, siginfo, stderr);
155          print_warning(sig, siginfo, log_file);
156          posix_print_stack_trace(log_file);
157          fclose(log_file);
158          log_file = NULL;
159       }
160
161     _Exit(1);
162 }
163 static uint8_t alternate_stack[SIGSTKSZ];
164 void set_signal_handler()
165 {
166     /* setup alternate stack */
167     {
168         stack_t ss = {};
169         /* malloc is usually used here, I'm not 100% sure my static allocation
170          is valid but it seems to work just fine. */
171         ss.ss_sp = (void*)alternate_stack;
172         ss.ss_size = SIGSTKSZ;
173         ss.ss_flags = 0;
174
175         if (sigaltstack(&ss, NULL) != 0) { err(1, "sigaltstack"); }
176     }
177
178     /* register our signal handlers */
179     {
180         struct sigaction sig_action = {};
181         sig_action.sa_sigaction = posix_signal_handler;
182         sigemptyset(&sig_action.sa_mask);
183
184         sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
185
186         if (sigaction(SIGSEGV, &sig_action, NULL) != 0) { err(1, "sigaction"); }
187         if (sigaction(SIGFPE,  &sig_action, NULL) != 0) { err(1, "sigaction"); }
188         if (sigaction(SIGINT,  &sig_action, NULL) != 0) { err(1, "sigaction"); }
189         if (sigaction(SIGILL,  &sig_action, NULL) != 0) { err(1, "sigaction"); }
190         if (sigaction(SIGTERM, &sig_action, NULL) != 0) { err(1, "sigaction"); }
191         if (sigaction(SIGABRT, &sig_action, NULL) != 0) { err(1, "sigaction"); }
192     }
193 }
194
195 static int app_create(void *data)
196 {
197    elm_init(0, NULL);
198
199    logger_init();
200    screen_reader_switch_enabled_set(EINA_TRUE);
201    screen_reader_create_service(data);
202 #ifndef SCREEN_READER_TV
203    screen_reader_gestures_init();
204    navigator_init();
205 #endif
206
207    return 0;
208 }
209
210 static int app_terminate(void *data)
211 {
212    DEBUG("screen reader terminating");
213
214 #ifndef SCREEN_READER_TV
215    DEBUG("terminate navigator");
216    navigator_shutdown();
217    DEBUG("terminate gestures");
218    screen_reader_gestures_shutdown();
219 #endif
220    DEBUG("terminate service");
221    screen_reader_terminate_service(data);
222    DEBUG("clear ScreenReaderEnabled property");
223    screen_reader_switch_enabled_set(EINA_FALSE);
224    DEBUG("terminate logger");
225    logger_shutdown();
226    DEBUG("screen reader terminated");
227    return 0;
228 }
229
230 int main(int argc, char **argv)
231 {
232    set_signal_handler();
233    unsetenv("ELM_ATSPI_MODE");
234
235    struct appcore_ops ops =
236    {
237       .create = app_create,
238       .terminate = app_terminate,
239       .pause = NULL,
240       .resume = NULL,
241       .reset = NULL
242    };
243    ops.data = get_pointer_to_service_data_struct();
244
245    return appcore_efl_main("screen-reader", &argc, &argv, &ops);
246 }