1 // Copyright (c) 2008, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 // Author: Satoru Takabayashi
32 // Implementation of InstallFailureSignalHandler().
34 #include "utilities.h"
35 #include "stacktrace.h"
36 #include "symbolize.h"
37 #include "glog/logging.h"
41 #ifdef HAVE_UCONTEXT_H
42 # include <ucontext.h>
44 #ifdef HAVE_SYS_UCONTEXT_H
45 # include <sys/ucontext.h>
49 _START_GOOGLE_NAMESPACE_
51 // TOOD(hamaji): Use signal instead of sigaction?
56 // We'll install the failure signal handler for these signals. We could
57 // use strsignal() to get signal names, but we don't use it to avoid
58 // introducing yet another #ifdef complication.
60 // The list should be synced with the comment in signalhandler.h.
64 } kFailureSignals[] = {
65 { SIGSEGV, "SIGSEGV" },
68 { SIGABRT, "SIGABRT" },
70 { SIGTERM, "SIGTERM" },
73 // Returns the program counter from signal context, NULL if unknown.
74 void* GetPC(void* ucontext_in_void) {
75 #if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
76 if (ucontext_in_void != NULL) {
77 ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
78 return (void*)context->PC_FROM_UCONTEXT;
84 // The class is used for formatting error messages. We don't use printf()
85 // as it's not async signal safe.
86 class MinimalFormatter {
88 MinimalFormatter(char *buffer, int size)
94 // Returns the number of bytes written in the buffer.
95 int num_bytes_written() const { return cursor_ - buffer_; }
97 // Appends string from "str" and updates the internal cursor.
98 void AppendString(const char* str) {
100 while (str[i] != '\0' && cursor_ + i < end_) {
107 // Formats "number" in "radix" and updates the internal cursor.
108 // Lowercase letters are used for 'a' - 'z'.
109 void AppendUint64(uint64 number, int radix) {
111 while (cursor_ + i < end_) {
112 const int tmp = number % radix;
114 cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
120 // Reverse the bytes written.
121 std::reverse(cursor_, cursor_ + i);
125 // Formats "number" as hexadecimal number, and updates the internal
126 // cursor. Padding will be added in front if needed.
127 void AppendHexWithPadding(uint64 number, int width) {
128 char* start = cursor_;
130 AppendUint64(number, 16);
131 // Move to right and add padding in front if needed.
132 if (cursor_ < start + width) {
133 const int64 delta = start + width - cursor_;
134 std::copy(start, cursor_, start + delta);
135 std::fill(start, start + delta, ' ');
136 cursor_ = start + width;
143 const char * const end_;
146 // Writes the given data with the size to the standard error.
147 void WriteToStderr(const char* data, int size) {
148 if (write(STDERR_FILENO, data, size) < 0) {
153 // The writer function can be changed by InstallFailureWriter().
154 void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
156 // Dumps time information. We don't dump human-readable time information
157 // as localtime() is not guaranteed to be async signal safe.
158 void DumpTimeInfo() {
159 time_t time_in_sec = time(NULL);
160 char buf[256]; // Big enough for time info.
161 MinimalFormatter formatter(buf, sizeof(buf));
162 formatter.AppendString("*** Aborted at ");
163 formatter.AppendUint64(time_in_sec, 10);
164 formatter.AppendString(" (unix time)");
165 formatter.AppendString(" try \"date -d @");
166 formatter.AppendUint64(time_in_sec, 10);
167 formatter.AppendString("\" if you are using GNU date ***\n");
168 g_failure_writer(buf, formatter.num_bytes_written());
171 // Dumps information about the signal to STDERR.
172 void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
173 // Get the signal name.
174 const char* signal_name = NULL;
175 for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
176 if (signal_number == kFailureSignals[i].number) {
177 signal_name = kFailureSignals[i].name;
181 char buf[256]; // Big enough for signal info.
182 MinimalFormatter formatter(buf, sizeof(buf));
184 formatter.AppendString("*** ");
186 formatter.AppendString(signal_name);
188 // Use the signal number if the name is unknown. The signal name
189 // should be known, but just in case.
190 formatter.AppendString("Signal ");
191 formatter.AppendUint64(signal_number, 10);
193 formatter.AppendString(" (@0x");
194 formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
195 formatter.AppendString(")");
196 formatter.AppendString(" received by PID ");
197 formatter.AppendUint64(getpid(), 10);
198 formatter.AppendString(" (TID 0x");
199 // We assume pthread_t is an integral number or a pointer, rather
200 // than a complex struct. In some environments, pthread_self()
201 // returns an uint64 but in some other environments pthread_self()
202 // returns a pointer. Hence we use C-style cast here, rather than
203 // reinterpret/static_cast, to support both types of environments.
204 formatter.AppendUint64((uintptr_t)pthread_self(), 16);
205 formatter.AppendString(") ");
206 // Only linux has the PID of the signal sender in si_pid.
208 formatter.AppendString("from PID ");
209 formatter.AppendUint64(siginfo->si_pid, 10);
210 formatter.AppendString("; ");
212 formatter.AppendString("stack trace: ***\n");
213 g_failure_writer(buf, formatter.num_bytes_written());
216 // Dumps information about the stack frame to STDERR.
217 void DumpStackFrameInfo(const char* prefix, void* pc) {
218 // Get the symbol name.
219 const char *symbol = "(unknown)";
220 char symbolized[1024]; // Big enough for a sane symbol.
221 // Symbolizes the previous address of pc because pc may be in the
223 if (Symbolize(reinterpret_cast<char *>(pc) - 1,
224 symbolized, sizeof(symbolized))) {
228 char buf[1024]; // Big enough for stack frame info.
229 MinimalFormatter formatter(buf, sizeof(buf));
231 formatter.AppendString(prefix);
232 formatter.AppendString("@ ");
233 const int width = 2 * sizeof(void*) + 2; // + 2 for "0x".
234 formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
235 formatter.AppendString(" ");
236 formatter.AppendString(symbol);
237 formatter.AppendString("\n");
238 g_failure_writer(buf, formatter.num_bytes_written());
241 // Invoke the default signal handler.
242 void InvokeDefaultSignalHandler(int signal_number) {
243 struct sigaction sig_action;
244 memset(&sig_action, 0, sizeof(sig_action));
245 sigemptyset(&sig_action.sa_mask);
246 sig_action.sa_handler = SIG_DFL;
247 sigaction(signal_number, &sig_action, NULL);
248 kill(getpid(), signal_number);
251 // This variable is used for protecting FailureSignalHandler() from
252 // dumping stuff while another thread is doing it. Our policy is to let
253 // the first thread dump stuff and let other threads wait.
254 // See also comments in FailureSignalHandler().
255 static pthread_t* g_entered_thread_id_pointer = NULL;
257 // Dumps signal and stack frame information, and invokes the default
258 // signal handler once our job is done.
259 void FailureSignalHandler(int signal_number,
260 siginfo_t *signal_info,
262 // First check if we've already entered the function. We use an atomic
263 // compare and swap operation for platforms that support it. For other
264 // platforms, we use a naive method that could lead to a subtle race.
266 // We assume pthread_self() is async signal safe, though it's not
267 // officially guaranteed.
268 pthread_t my_thread_id = pthread_self();
269 // NOTE: We could simply use pthread_t rather than pthread_t* for this,
270 // if pthread_self() is guaranteed to return non-zero value for thread
271 // ids, but there is no such guarantee. We need to distinguish if the
272 // old value (value returned from __sync_val_compare_and_swap) is
273 // different from the original value (in this case NULL).
274 pthread_t* old_thread_id_pointer =
275 glog_internal_namespace_::sync_val_compare_and_swap(
276 &g_entered_thread_id_pointer,
277 static_cast<pthread_t*>(NULL),
279 if (old_thread_id_pointer != NULL) {
280 // We've already entered the signal handler. What should we do?
281 if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
282 // It looks the current thread is reentering the signal handler.
283 // Something must be going wrong (maybe we are reentering by another
284 // type of signal?). Kill ourself by the default signal handler.
285 InvokeDefaultSignalHandler(signal_number);
287 // Another thread is dumping stuff. Let's wait until that thread
288 // finishes the job and kills the process.
293 // This is the first time we enter the signal handler. We are going to
294 // do some interesting stuff from here.
295 // TODO(satorux): We might want to set timeout here using alarm(), but
296 // mixing alarm() and sleep() can be a bad idea.
298 // First dump time info.
301 // Get the program counter from ucontext.
302 void *pc = GetPC(ucontext);
303 DumpStackFrameInfo("PC: ", pc);
305 #ifdef HAVE_STACKTRACE
306 // Get the stack traces.
308 // +1 to exclude this function.
309 const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
310 DumpSignalInfo(signal_number, signal_info);
311 // Dump the stack traces.
312 for (int i = 0; i < depth; ++i) {
313 DumpStackFrameInfo(" ", stack[i]);
317 // *** TRANSITION ***
319 // BEFORE this point, all code must be async-termination-safe!
320 // (See WARNING above.)
322 // AFTER this point, we do unsafe things, like using LOG()!
323 // The process could be terminated or hung at any time. We try to
324 // do more useful things first and riskier things later.
326 // Flush the logs before we do anything in case 'anything'
328 FlushLogFilesUnsafe(0);
330 // Kill ourself by the default signal handler.
331 InvokeDefaultSignalHandler(signal_number);
336 #endif // HAVE_SIGACTION
338 namespace glog_internal_namespace_ {
340 bool IsFailureSignalHandlerInstalled() {
341 #ifdef HAVE_SIGACTION
342 struct sigaction sig_action;
343 memset(&sig_action, 0, sizeof(sig_action));
344 sigemptyset(&sig_action.sa_mask);
345 sigaction(SIGABRT, NULL, &sig_action);
346 if (sig_action.sa_sigaction == &FailureSignalHandler)
348 #endif // HAVE_SIGACTION
352 } // namespace glog_internal_namespace_
354 void InstallFailureSignalHandler() {
355 #ifdef HAVE_SIGACTION
356 // Build the sigaction struct.
357 struct sigaction sig_action;
358 memset(&sig_action, 0, sizeof(sig_action));
359 sigemptyset(&sig_action.sa_mask);
360 sig_action.sa_flags |= SA_SIGINFO;
361 sig_action.sa_sigaction = &FailureSignalHandler;
363 for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
364 CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
366 #endif // HAVE_SIGACTION
369 void InstallFailureWriter(void (*writer)(const char* data, int size)) {
370 #ifdef HAVE_SIGACTION
371 g_failure_writer = writer;
372 #endif // HAVE_SIGACTION
375 _END_GOOGLE_NAMESPACE_