at v4.9-rc2 176 lines 3.2 kB view raw
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 19static volatile int ui__need_resize; 20 21extern struct perf_error_ops perf_tui_eops; 22extern bool tui_helpline__set; 23 24extern void hist_browser__init_hpp(void); 25 26void 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 37static void ui__sigwinch(int sig __maybe_unused) 38{ 39 ui__need_resize = 1; 40} 41 42static 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 54int 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 98static 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 116static void ui__signal(int sig) 117{ 118 ui__exit(false); 119 psignal(sig, "perf"); 120 exit(0); 121} 122 123int 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(); 159out: 160 return err; 161} 162 163void 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}