1 // Copyright 2008 Google Inc. All Rights Reserved.
2 // Author: Satoru Takabayashi
4 // Implementation of InstallFailureSignalHandler().
7 #include "stacktrace.h"
9 #include "glog/logging.h"
13 #ifdef HAVE_UCONTEXT_H
14 # include <ucontext.h>
18 _START_GOOGLE_NAMESPACE_
20 // There is a better way, but this is good enough in this file.
21 #define NAIVE_ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
25 // Wrapper of __sync_val_compare_and_swap. If the GCC extension isn't
26 // defined, we try the CPU specific logics (we only support x86 and
27 // x86_64 for now) first, then use a naive implementation, which has a
30 inline T* sync_val_compare_and_swap(T** ptr, T* oldval, T* newval) {
31 #if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP)
32 return __sync_val_compare_and_swap(ptr, oldval, newval);
33 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
35 __asm__ __volatile__("lock; cmpxchg %1, (%2);"
37 :"r"(newval), "r"(ptr), "a"(oldval)
49 // We'll install the failure signal handler for these signals. We could
50 // use strsignal() to get signal names, but we don't use it to avoid
51 // introducing yet another #ifdef complication.
53 // The list should be synced with the comment in signalhandler.h.
57 } kFailureSignals[] = {
58 { SIGSEGV, "SIGSEGV" },
61 { SIGABRT, "SIGABRT" },
63 { SIGTERM, "SIGTERM" },
66 // Returns the program counter from signal context, NULL if unknown.
67 void* GetPC(void* ucontext_in_void) {
68 #if defined(HAVE_UCONTEXT_H) && defined(PC_FROM_UCONTEXT)
69 if (ucontext_in_void != NULL) {
70 ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
71 return (void*)context->PC_FROM_UCONTEXT;
77 // The class is used for formatting error messages. We don't use printf()
78 // as it's not async signal safe.
79 class MinimalFormatter {
81 MinimalFormatter(char *buffer, int size)
87 // Returns the number of bytes written in the buffer.
88 int num_bytes_written() const { return cursor_ - buffer_; }
90 // Appends string from "str" and updates the internal cursor.
91 void AppendString(const char* str) {
93 while (str[i] != '\0' && cursor_ + i < end_) {
100 // Formats "number" in "radix" and updates the internal cursor.
101 // Lowercase letters are used for 'a' - 'z'.
102 void AppendUint64(uint64 number, int radix) {
104 while (cursor_ + i < end_) {
105 const int tmp = number % radix;
107 cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
113 // Reverse the bytes written.
114 std::reverse(cursor_, cursor_ + i);
118 // Formats "number" as hexadecimal number, and updates the internal
119 // cursor. Padding will be added in front if needed.
120 void AppendHexWithPadding(uint64 number, int width) {
121 char* start = cursor_;
123 AppendUint64(number, 16);
124 // Move to right and add padding in front if needed.
125 if (cursor_ < start + width) {
126 const int64 delta = start + width - cursor_;
127 std::copy(start, cursor_, start + delta);
128 std::fill(start, start + delta, ' ');
129 cursor_ = start + width;
136 const char * const end_;
139 // Writes the given data with the size to the standard error.
140 void WriteToStderr(const char* data, int size) {
141 write(STDERR_FILENO, data, size);
144 // The writer function can be changed by InstallFailureWriter().
145 void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
147 // Dumps time information. We don't dump human-readable time information
148 // as localtime() is not guaranteed to be async signal safe.
149 void DumpTimeInfo() {
150 time_t time_in_sec = time(NULL);
151 char buf[256]; // Big enough for time info.
152 MinimalFormatter formatter(buf, sizeof(buf));
153 formatter.AppendString("*** Aborted at ");
154 formatter.AppendUint64(time_in_sec, 10);
155 formatter.AppendString(" (unix time)");
156 formatter.AppendString(" try \"date -d @");
157 formatter.AppendUint64(time_in_sec, 10);
158 formatter.AppendString("\" if you are using GNU date ***\n");
159 g_failure_writer(buf, formatter.num_bytes_written());
162 // Dumps information about the signal to STDERR.
163 void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
164 // Get the signal name.
165 const char* signal_name = NULL;
166 for (int i = 0; i < NAIVE_ARRAYSIZE(kFailureSignals); ++i) {
167 if (signal_number == kFailureSignals[i].number) {
168 signal_name = kFailureSignals[i].name;
172 char buf[256]; // Big enough for signal info.
173 MinimalFormatter formatter(buf, sizeof(buf));
175 formatter.AppendString("*** ");
177 formatter.AppendString(signal_name);
179 // Use the signal number if the name is unknown. The signal name
180 // should be known, but just in case.
181 formatter.AppendString("Signal ");
182 formatter.AppendUint64(signal_number, 10);
184 formatter.AppendString(" (@0x");
185 formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
186 formatter.AppendString(")");
187 formatter.AppendString(" received by PID ");
188 formatter.AppendUint64(getpid(), 10);
189 formatter.AppendString(" (TID 0x");
190 // We assume pthread_t is an integral number or a pointer, rather
191 // than a complex struct. In some environments, pthread_self()
192 // returns an uint64 but in some other environments pthread_self()
193 // returns a pointer. Hence we use C-style cast here, rather than
194 // reinterpret/static_cast, to support both types of environments.
195 formatter.AppendUint64((uintptr_t)pthread_self(), 16);
196 formatter.AppendString(") ");
197 // Only linux has the PID of the signal sender in si_pid.
199 formatter.AppendString("from PID ");
200 formatter.AppendUint64(siginfo->si_pid, 10);
201 formatter.AppendString("; ");
203 formatter.AppendString("stack trace: ***\n");
204 g_failure_writer(buf, formatter.num_bytes_written());
207 // Dumps information about the stack frame to STDERR.
208 void DumpStackFrameInfo(const char* prefix, void* pc) {
209 // Get the symbol name.
210 const char *symbol = "(unknown)";
211 char symbolized[1024]; // Big enough for a sane symbol.
212 // Symbolizes the previous address of pc because pc may be in the
214 if (Symbolize(reinterpret_cast<char *>(pc) - 1,
215 symbolized, sizeof(symbolized))) {
219 char buf[1024]; // Big enough for stack frame info.
220 MinimalFormatter formatter(buf, sizeof(buf));
222 formatter.AppendString(prefix);
223 formatter.AppendString("@ ");
224 const int width = 2 * sizeof(void*) + 2; // + 2 for "0x".
225 formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
226 formatter.AppendString(" ");
227 formatter.AppendString(symbol);
228 formatter.AppendString("\n");
229 g_failure_writer(buf, formatter.num_bytes_written());
232 // Invoke the default signal handler.
233 void InvokeDefaultSignalHandler(int signal_number) {
234 struct sigaction sig_action = {}; // Zero-clear.
235 sigemptyset(&sig_action.sa_mask);
236 sig_action.sa_handler = SIG_DFL;
237 sigaction(signal_number, &sig_action, NULL);
238 kill(getpid(), signal_number);
241 // This variable is used for protecting FailureSignalHandler() from
242 // dumping stuff while another thread is doing it. Our policy is to let
243 // the first thread dump stuff and let other threads wait.
244 // See also comments in FailureSignalHandler().
245 static pthread_t* g_entered_thread_id_pointer = NULL;
247 // Dumps signal and stack frame information, and invokes the default
248 // signal handler once our job is done.
249 void FailureSignalHandler(int signal_number,
250 siginfo_t *signal_info,
252 // First check if we've already entered the function. We use an atomic
253 // compare and swap operation for platforms that support it. For other
254 // platforms, we use a naive method that could lead to a subtle race.
256 // We assume pthread_self() is async signal safe, though it's not
257 // officially guaranteed.
258 pthread_t my_thread_id = pthread_self();
259 // NOTE: We could simply use pthread_t rather than pthread_t* for this,
260 // if pthread_self() is guaranteed to return non-zero value for thread
261 // ids, but there is no such guarantee. We need to distinguish if the
262 // old value (value returned from __sync_val_compare_and_swap) is
263 // different from the original value (in this case NULL).
264 pthread_t* old_thread_id_pointer =
265 sync_val_compare_and_swap(&g_entered_thread_id_pointer,
266 static_cast<pthread_t*>(NULL),
268 if (old_thread_id_pointer != NULL) {
269 // We've already entered the signal handler. What should we do?
270 if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
271 // It looks the current thread is reentering the signal handler.
272 // Something must be going wrong (maybe we are reentering by another
273 // type of signal?). Kill ourself by the default signal handler.
274 InvokeDefaultSignalHandler(signal_number);
276 // Another thread is dumping stuff. Let's wait until that thread
277 // finishes the job and kills the process.
282 // This is the first time we enter the signal handler. We are going to
283 // do some interesting stuff from here.
284 // TODO(satorux): We might want to set timeout here using alarm(), but
285 // mixing alarm() and sleep() can be a bad idea.
287 // First dump time info.
290 // Get the program counter from ucontext.
291 void *pc = GetPC(ucontext);
292 DumpStackFrameInfo("PC: ", pc);
294 #ifdef HAVE_STACKTRACE
295 // Get the stack traces.
297 // +1 to exclude this function.
298 const int depth = GetStackTrace(stack, NAIVE_ARRAYSIZE(stack), 1);
299 DumpSignalInfo(signal_number, signal_info);
300 // Dump the stack traces.
301 for (int i = 0; i < depth; ++i) {
302 DumpStackFrameInfo(" ", stack[i]);
305 // Kill ourself by the default signal handler.
306 InvokeDefaultSignalHandler(signal_number);
311 void InstallFailureSignalHandler() {
312 // Build the sigaction struct.
313 struct sigaction sig_action = {}; // Zero-clear.
314 sigemptyset(&sig_action.sa_mask);
315 sig_action.sa_flags |= SA_SIGINFO;
316 sig_action.sa_sigaction = &FailureSignalHandler;
318 for (int i = 0; i < NAIVE_ARRAYSIZE(kFailureSignals); ++i) {
319 CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
323 void InstallFailureWriter(void (*writer)(const char* data, int size)) {
324 g_failure_writer = writer;
327 _END_GOOGLE_NAMESPACE_