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.
SafePrintStackTrace()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
StacktraceHandler(int sig,siginfo_t * si,void * v)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
InstallStacktraceHandler()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