1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 #include "tensorflow/core/platform/platform.h" 17 18 #if !defined(PLATFORM_GOOGLE) && !defined(IS_MOBILE_PLATFORM) && \ 19 defined(PLATFORM_POSIX) && (defined(__clang__) || defined(__GNUC__)) 20 #define TF_GENERATE_STACKTRACE 21 #endif 22 23 #if defined(TF_GENERATE_STACKTRACE) 24 #include <errno.h> 25 #include <signal.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/time.h> 30 #include <unistd.h> 31 #include <string> 32 33 #include "tensorflow/core/platform/abi.h" 34 #include "tensorflow/core/platform/stacktrace.h" 35 36 #endif // defined(TF_GENERATE_STACKTRACE) 37 38 namespace tensorflow { 39 namespace testing { 40 41 #if defined(TF_GENERATE_STACKTRACE) 42 // This function will print stacktrace to STDERR. 43 // It avoids using malloc, so it makes sure to dump the stack even when the heap 44 // is corrupted. However, it can dump mangled symbols. 45 inline void SafePrintStackTrace() { 46 static const char begin_msg[] = "*** BEGIN MANGLED STACK TRACE ***\n"; 47 (void)write(STDERR_FILENO, begin_msg, strlen(begin_msg)); 48 49 int buffer_size = 128; 50 void *trace[128]; 51 // Run backtrace to get the size of the stacktrace 52 buffer_size = backtrace(trace, buffer_size); 53 54 // Print a mangled stacktrace to STDERR as safely as possible. 55 backtrace_symbols_fd(trace, buffer_size, STDERR_FILENO); 56 57 static const char end_msg[] = "*** END MANGLED STACK TRACE ***\n\n"; 58 (void)write(STDERR_FILENO, end_msg, strlen(end_msg)); 59 } 60 61 static void StacktraceHandler(int sig, siginfo_t *si, void *v) { 62 // Make sure our handler does not deadlock. And this should be the last thing 63 // our program does. Therefore, set a timer to kill the program in 60 64 // seconds. 65 struct itimerval timer; 66 timer.it_value.tv_sec = 60; 67 timer.it_value.tv_usec = 0; 68 timer.it_interval.tv_sec = 0; 69 timer.it_interval.tv_usec = 0; 70 setitimer(ITIMER_REAL, &timer, 0); 71 72 struct sigaction sa_timeout; 73 memset(&sa_timeout, 0, sizeof(sa_timeout)); 74 sa_timeout.sa_handler = SIG_DFL; 75 sigaction(SIGALRM, &sa_timeout, 0); 76 77 char buf[128]; 78 79 snprintf(buf, sizeof(buf), "*** Received signal %d ***\n", sig); 80 (void)write(STDERR_FILENO, buf, strlen(buf)); 81 82 // Print "a" stack trace, as safely as possible. 83 SafePrintStackTrace(); 84 85 // Up until this line, we made sure not to allocate memory, to be able to dump 86 // a stack trace even in the event of heap corruption. After this line, we 87 // will try to print more human readable things to the terminal. 88 // But these have a higher probability to fail. 89 std::string stacktrace = CurrentStackTrace(); 90 (void)write(STDERR_FILENO, stacktrace.c_str(), stacktrace.length()); 91 92 // Abort the program. 93 struct sigaction sa; 94 sigemptyset(&sa.sa_mask); 95 sa.sa_flags = 0; 96 sa.sa_handler = SIG_DFL; 97 sigaction(SIGABRT, &sa, NULL); 98 abort(); 99 } 100 101 void InstallStacktraceHandler() { 102 int handled_signals[] = {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE}; 103 104 for (int i = 0; i < sizeof(handled_signals) / sizeof(int); i++) { 105 int sig = handled_signals[i]; 106 struct sigaction sa; 107 struct sigaction osa; 108 109 sigemptyset(&sa.sa_mask); 110 sa.sa_flags = SA_SIGINFO | SA_RESETHAND; 111 sa.sa_sigaction = &StacktraceHandler; 112 if (sigaction(sig, &sa, &osa) != 0) { 113 char buf[128]; 114 snprintf(buf, sizeof(buf), 115 "Warning, can't install backtrace signal handler for signal %d, " 116 "errno:%d \n", 117 sig, errno); 118 (void)write(STDERR_FILENO, buf, strlen(buf)); 119 } else if (osa.sa_handler != SIG_DFL) { 120 char buf[128]; 121 snprintf(buf, sizeof(buf), 122 "Warning, backtrace signal handler for signal %d overwrote " 123 "previous handler.\n", 124 sig); 125 (void)write(STDERR_FILENO, buf, strlen(buf)); 126 } 127 } 128 } 129 130 #else 131 void InstallStacktraceHandler() {} 132 #endif // defined(TF_GENERATE_STACKTRACE) 133 134 } // namespace testing 135 } // namespace tensorflow 136