2 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://floralicense.org/license/
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.
21 #include <appcore-efl.h>
22 #include <Elementary.h>
23 #include <eldbus-1/Eldbus.h>
24 #include "navigator.h"
25 #include "window_tracker.h"
27 #include "screen_reader.h"
28 #include "screen_reader_gestures.h"
29 #include "screen_reader_switch.h"
31 #define MAX_STACK_FRAMES 64
32 static void *stack_traces[MAX_STACK_FRAMES];
34 void posix_print_stack_trace(FILE *log_file)
36 int i, trace_size = 0;
37 char **messages = (char **)NULL;
39 trace_size = backtrace(stack_traces, MAX_STACK_FRAMES);
40 messages = backtrace_symbols(stack_traces, trace_size);
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
47 fprintf(log_file, " BACKTRACE LINE %i: %s\n",i, messages[i]);
49 if (messages) { free(messages); }
52 void print_warning(int sig, siginfo_t *siginfo, FILE *log_file)
57 fputs("Caught SIGSEGV: Segmentation Fault\n", log_file);
60 fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", log_file);
63 switch(siginfo->si_code)
66 fputs("Caught SIGFPE: (integer divide by zero)\n", log_file);
69 fputs("Caught SIGFPE: (integer overflow)\n", log_file);
72 fputs("Caught SIGFPE: (floating-point divide by zero)\n", log_file);
75 fputs("Caught SIGFPE: (floating-point overflow)\n", log_file);
78 fputs("Caught SIGFPE: (floating-point underflow)\n", log_file);
81 fputs("Caught SIGFPE: (floating-point inexact result)\n", log_file);
84 fputs("Caught SIGFPE: (floating-point invalid operation)\n", log_file);
87 fputs("Caught SIGFPE: (subscript out of range)\n", log_file);
90 fputs("Caught SIGFPE: Arithmetic Exception\n", log_file);
95 switch(siginfo->si_code)
98 fputs("Caught SIGILL: (illegal opcode)\n", log_file);
101 fputs("Caught SIGILL: (illegal operand)\n", log_file);
104 fputs("Caught SIGILL: (illegal addressing mode)\n", log_file);
107 fputs("Caught SIGILL: (illegal trap)\n", log_file);
110 fputs("Caught SIGILL: (privileged opcode)\n", log_file);
113 fputs("Caught SIGILL: (privileged register)\n", log_file);
116 fputs("Caught SIGILL: (coprocessor error)\n", log_file);
119 fputs("Caught SIGILL: (internal stack error)\n", log_file);
122 fputs("Caught SIGILL: Illegal Instruction\n", log_file);
127 fputs("Caught SIGTERM: a termination request was sent to the program\n", log_file);
130 fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", log_file);
138 void posix_signal_handler(int sig, siginfo_t *siginfo, void *context)
140 char file_name[256] = {0};
141 struct tm * timeinfo;
142 time_t rawtime = time(NULL);
143 timeinfo = localtime(&rawtime);
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());
148 sprintf(file_name, "/tmp/screen_reader_crash_stacktrace_pid_%i.log", getpid());
150 FILE * log_file = fopen(file_name, "w");
154 print_warning(sig, siginfo, stderr);
155 print_warning(sig, siginfo, log_file);
156 posix_print_stack_trace(log_file);
163 static uint8_t alternate_stack[SIGSTKSZ];
164 void set_signal_handler()
166 /* setup alternate stack */
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;
175 if (sigaltstack(&ss, NULL) != 0) { err(1, "sigaltstack"); }
178 /* register our signal handlers */
180 struct sigaction sig_action = {};
181 sig_action.sa_sigaction = posix_signal_handler;
182 sigemptyset(&sig_action.sa_mask);
184 sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
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"); }
195 static int app_create(void *data)
200 screen_reader_switch_enabled_set(EINA_TRUE);
201 screen_reader_create_service(data);
202 #ifdef SCREEN_READER_MOBILE
203 screen_reader_gestures_init();
210 static int app_terminate(void *data)
212 DEBUG("screen reader terminating");
214 #ifdef SCREEN_READER_MOBILE
215 DEBUG("terminate navigator");
216 navigator_shutdown();
217 DEBUG("terminate gestures");
218 screen_reader_gestures_shutdown();
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");
226 DEBUG("screen reader terminated");
230 int main(int argc, char **argv)
232 set_signal_handler();
233 unsetenv("ELM_ATSPI_MODE");
235 struct appcore_ops ops =
237 .create = app_create,
238 .terminate = app_terminate,
243 ops.data = get_pointer_to_service_data_struct();
245 return appcore_efl_main("screen-reader", &argc, &argv, &ops);