• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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