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>
25 #ifndef SCREEN_READER_TV
26 #include "navigator.h"
27 #include "screen_reader_gestures.h"
30 #include "screen_reader.h"
31 #include "screen_reader_switch.h"
33 #define MAX_STACK_FRAMES 64
34 static void *stack_traces[MAX_STACK_FRAMES];
36 void posix_print_stack_trace(FILE * log_file)
38 int i, trace_size = 0;
39 char **messages = (char **)NULL;
41 trace_size = backtrace(stack_traces, MAX_STACK_FRAMES);
42 messages = backtrace_symbols(stack_traces, trace_size);
44 /* skip the first couple stack frames (as they are this function and
45 our handler) and also skip the last frame as it's (always?) junk. */
46 // for (i = 3; i < (trace_size - 1); ++i)
47 for (i = 0; i < trace_size; ++i) // we'll use this for now so you can see what's going on
49 fprintf(log_file, " BACKTRACE LINE %i: %s\n", i, messages[i]);
56 void print_warning(int sig, siginfo_t * siginfo, FILE * log_file)
60 fputs("Caught SIGSEGV: Segmentation Fault\n", log_file);
63 fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", log_file);
66 switch (siginfo->si_code) {
68 fputs("Caught SIGFPE: (integer divide by zero)\n", log_file);
71 fputs("Caught SIGFPE: (integer overflow)\n", log_file);
74 fputs("Caught SIGFPE: (floating-point divide by zero)\n", log_file);
77 fputs("Caught SIGFPE: (floating-point overflow)\n", log_file);
80 fputs("Caught SIGFPE: (floating-point underflow)\n", log_file);
83 fputs("Caught SIGFPE: (floating-point inexact result)\n", log_file);
86 fputs("Caught SIGFPE: (floating-point invalid operation)\n", log_file);
89 fputs("Caught SIGFPE: (subscript out of range)\n", log_file);
92 fputs("Caught SIGFPE: Arithmetic Exception\n", log_file);
97 switch (siginfo->si_code) {
99 fputs("Caught SIGILL: (illegal opcode)\n", log_file);
102 fputs("Caught SIGILL: (illegal operand)\n", log_file);
105 fputs("Caught SIGILL: (illegal addressing mode)\n", log_file);
108 fputs("Caught SIGILL: (illegal trap)\n", log_file);
111 fputs("Caught SIGILL: (privileged opcode)\n", log_file);
114 fputs("Caught SIGILL: (privileged register)\n", log_file);
117 fputs("Caught SIGILL: (coprocessor error)\n", log_file);
120 fputs("Caught SIGILL: (internal stack error)\n", log_file);
123 fputs("Caught SIGILL: Illegal Instruction\n", log_file);
128 fputs("Caught SIGTERM: a termination request was sent to the program\n", log_file);
131 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)
142 time_t rawtime = time(NULL);
143 timeinfo = localtime(&rawtime);
145 snprintf(file_name, sizeof(file_name), "/tmp/screen_reader_crash_stacktrace_%i%i%i_%i:%i:%i_pid_%i.log", timeinfo->tm_year, timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, getpid());
147 snprintf(file_name, sizeof(file_name), "/tmp/screen_reader_crash_stacktrace_pid_%i.log", getpid());
149 FILE *log_file = fopen(file_name, "w");
152 print_warning(sig, siginfo, stderr);
154 /* check file if it is symbolic link */
155 struct stat lstat_info;
156 if (lstat(file_name, &lstat_info) != -1) {
157 print_warning(sig, siginfo, log_file);
158 posix_print_stack_trace(log_file);
168 static uint8_t alternate_stack[SIGSTKSZ];
169 void set_signal_handler()
171 /* setup alternate stack */
174 /* malloc is usually used here, I'm not 100% sure my static allocation
175 is valid but it seems to work just fine. */
176 ss.ss_sp = (void *)alternate_stack;
177 ss.ss_size = SIGSTKSZ;
180 if (sigaltstack(&ss, NULL) != 0) {
181 err(1, "sigaltstack");
185 /* register our signal handlers */
187 struct sigaction sig_action = { };
188 sig_action.sa_sigaction = posix_signal_handler;
189 sigemptyset(&sig_action.sa_mask);
191 sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
193 if (sigaction(SIGSEGV, &sig_action, NULL) != 0) {
196 if (sigaction(SIGFPE, &sig_action, NULL) != 0) {
199 if (sigaction(SIGINT, &sig_action, NULL) != 0) {
202 if (sigaction(SIGILL, &sig_action, NULL) != 0) {
205 if (sigaction(SIGTERM, &sig_action, NULL) != 0) {
208 if (sigaction(SIGABRT, &sig_action, NULL) != 0) {
214 static int app_create(void *data)
216 if (vconf_set_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, 1))
217 ERROR("Can't set value of %s vconf key to 1", VCONFKEY_SETAPPL_ACCESSIBILITY_TTS);
221 screen_reader_create_service(data);
222 #ifndef SCREEN_READER_TV
223 screen_reader_gestures_init();
226 screen_reader_switch_enabled_set(EINA_TRUE);
230 static int app_terminate(void *data)
232 DEBUG("screen reader terminating");
233 #ifndef SCREEN_READER_TV
234 DEBUG("terminate navigator");
235 navigator_shutdown();
236 DEBUG("terminate gestures");
237 screen_reader_gestures_shutdown();
239 DEBUG("terminate service");
240 screen_reader_terminate_service(data);
241 DEBUG("clear ScreenReaderEnabled property");
242 screen_reader_switch_enabled_set(EINA_FALSE);
243 DEBUG("screen reader terminated");
245 DEBUG("libatspi terminated");
247 if (vconf_set_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, 0))
248 ERROR("Can't set value of %s vconf key to 1", VCONFKEY_SETAPPL_ACCESSIBILITY_TTS);
252 int main(int argc, char **argv)
254 set_signal_handler();
255 unsetenv("ELM_ATSPI_MODE");
257 struct appcore_ops ops = {
258 .create = app_create,
259 .terminate = app_terminate,
264 ops.data = get_pointer_to_service_data_struct();
266 return appcore_efl_main("screen-reader", &argc, &argv, &ops);