1 #include <errno.h> 2 #include <signal.h> 3 #include <stdbool.h> 4 #ifdef HAVE_BACKTRACE_SUPPORT 5 #include <execinfo.h> 6 #endif 7 8 #include "../../util/cache.h" 9 #include "../../util/debug.h" 10 #include "../../util/util.h" 11 #include "../browser.h" 12 #include "../helpline.h" 13 #include "../ui.h" 14 #include "../util.h" 15 #include "../libslang.h" 16 #include "../keysyms.h" 17 #include "tui.h" 18 19 static volatile int ui__need_resize; 20 21 extern struct perf_error_ops perf_tui_eops; 22 extern bool tui_helpline__set; 23 24 extern void hist_browser__init_hpp(void); 25 26 void ui__refresh_dimensions(bool force) 27 { 28 if (force || ui__need_resize) { 29 ui__need_resize = 0; 30 pthread_mutex_lock(&ui__lock); 31 SLtt_get_screen_size(); 32 SLsmg_reinit_smg(); 33 pthread_mutex_unlock(&ui__lock); 34 } 35 } 36 37 static void ui__sigwinch(int sig __maybe_unused) 38 { 39 ui__need_resize = 1; 40 } 41 42 static void ui__setup_sigwinch(void) 43 { 44 static bool done; 45 46 if (done) 47 return; 48 49 done = true; 50 pthread__unblock_sigwinch(); 51 signal(SIGWINCH, ui__sigwinch); 52 } 53 54 int ui__getch(int delay_secs) 55 { 56 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; 57 fd_set read_set; 58 int err, key; 59 60 ui__setup_sigwinch(); 61 62 FD_ZERO(&read_set); 63 FD_SET(0, &read_set); 64 65 if (delay_secs) { 66 timeout.tv_sec = delay_secs; 67 timeout.tv_usec = 0; 68 } 69 70 err = select(1, &read_set, NULL, NULL, ptimeout); 71 72 if (err == 0) 73 return K_TIMER; 74 75 if (err == -1) { 76 if (errno == EINTR) 77 return K_RESIZE; 78 return K_ERROR; 79 } 80 81 key = SLang_getkey(); 82 if (key != K_ESC) 83 return key; 84 85 FD_ZERO(&read_set); 86 FD_SET(0, &read_set); 87 timeout.tv_sec = 0; 88 timeout.tv_usec = 20; 89 err = select(1, &read_set, NULL, NULL, &timeout); 90 if (err == 0) 91 return K_ESC; 92 93 SLang_ungetkey(key); 94 return SLkp_getkey(); 95 } 96 97 #ifdef HAVE_BACKTRACE_SUPPORT 98 static void ui__signal_backtrace(int sig) 99 { 100 void *stackdump[32]; 101 size_t size; 102 103 ui__exit(false); 104 psignal(sig, "perf"); 105 106 printf("-------- backtrace --------\n"); 107 size = backtrace(stackdump, ARRAY_SIZE(stackdump)); 108 backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); 109 110 exit(0); 111 } 112 #else 113 # define ui__signal_backtrace ui__signal 114 #endif 115 116 static void ui__signal(int sig) 117 { 118 ui__exit(false); 119 psignal(sig, "perf"); 120 exit(0); 121 } 122 123 int ui__init(void) 124 { 125 int err; 126 127 SLutf8_enable(-1); 128 SLtt_get_terminfo(); 129 SLtt_get_screen_size(); 130 131 err = SLsmg_init_smg(); 132 if (err < 0) 133 goto out; 134 err = SLang_init_tty(-1, 0, 0); 135 if (err < 0) 136 goto out; 137 138 err = SLkp_init(); 139 if (err < 0) { 140 pr_err("TUI initialization failed.\n"); 141 goto out; 142 } 143 144 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); 145 146 signal(SIGSEGV, ui__signal_backtrace); 147 signal(SIGFPE, ui__signal_backtrace); 148 signal(SIGINT, ui__signal); 149 signal(SIGQUIT, ui__signal); 150 signal(SIGTERM, ui__signal); 151 152 perf_error__register(&perf_tui_eops); 153 154 ui_helpline__init(); 155 ui_browser__init(); 156 tui_progress__init(); 157 158 hist_browser__init_hpp(); 159 out: 160 return err; 161 } 162 163 void ui__exit(bool wait_for_ok) 164 { 165 if (wait_for_ok && tui_helpline__set) 166 ui__question_window("Fatal Error", 167 ui_helpline__last_msg, 168 "Press any key...", 0); 169 170 SLtt_set_cursor_visibility(1); 171 SLsmg_refresh(); 172 SLsmg_reset_smg(); 173 SLang_reset_tty(); 174 175 perf_error__unregister(&perf_tui_eops); 176 } 177