OLD | NEW |
1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include <config.h> | 33 #include <config.h> |
34 #include "internal_logging.h" | 34 #include "internal_logging.h" |
35 #include <stdarg.h> // for va_end, va_start | 35 #include <stdarg.h> // for va_end, va_start |
36 #include <stdio.h> // for vsnprintf, va_list, etc | 36 #include <stdio.h> // for vsnprintf, va_list, etc |
37 #include <stdlib.h> // for abort | 37 #include <stdlib.h> // for abort |
38 #include <string.h> // for strlen, memcpy | 38 #include <string.h> // for strlen, memcpy |
39 #ifdef HAVE_UNISTD_H | 39 #ifdef HAVE_UNISTD_H |
40 #include <unistd.h> // for write() | 40 #include <unistd.h> // for write() |
41 #endif | 41 #endif |
42 | 42 |
43 #include <google/malloc_extension.h> | 43 #include <gperftools/malloc_extension.h> |
44 #include "base/logging.h" // for perftools_vsnprintf | 44 #include "base/logging.h" // for perftools_vsnprintf |
45 #include "base/spinlock.h" // for SpinLockHolder, SpinLock | 45 #include "base/spinlock.h" // for SpinLockHolder, SpinLock |
46 | 46 |
47 static const int kLogBufSize = 800; | 47 static const int kLogBufSize = 800; |
48 | 48 |
49 void TCMalloc_MESSAGE(const char* filename, | 49 // Variables for storing crash output. Allocated statically since we |
50 int line_number, | 50 // may not be able to heap-allocate while crashing. |
51 const char* format, ...) { | 51 static SpinLock crash_lock(base::LINKER_INITIALIZED); |
52 char buf[kLogBufSize]; | 52 static bool crashed = false; |
53 const int n = snprintf(buf, sizeof(buf), "%s:%d] ", filename, line_number); | |
54 if (n < kLogBufSize) { | |
55 va_list ap; | |
56 va_start(ap, format); | |
57 perftools_vsnprintf(buf + n, kLogBufSize - n, format, ap); | |
58 va_end(ap); | |
59 } | |
60 write(STDERR_FILENO, buf, strlen(buf)); | |
61 } | |
62 | |
63 static const int kStatsBufferSize = 16 << 10; | 53 static const int kStatsBufferSize = 16 << 10; |
64 static char stats_buffer[kStatsBufferSize] = { 0 }; | 54 static char stats_buffer[kStatsBufferSize] = { 0 }; |
65 | 55 |
66 static void TCMalloc_CRASH_internal(bool dump_stats, | 56 namespace tcmalloc { |
67 const char* filename, | 57 |
68 int line_number, | 58 static void WriteMessage(const char* msg, int length) { |
69 const char* format, va_list ap) { | 59 write(STDERR_FILENO, msg, length); |
70 char buf[kLogBufSize]; | 60 } |
71 const int n = snprintf(buf, sizeof(buf), "%s:%d] ", filename, line_number); | 61 |
72 if (n < kLogBufSize) { | 62 void (*log_message_writer)(const char* msg, int length) = WriteMessage; |
73 perftools_vsnprintf(buf + n, kLogBufSize - n, format, ap); | 63 |
| 64 |
| 65 class Logger { |
| 66 public: |
| 67 bool Add(const LogItem& item); |
| 68 bool AddStr(const char* str, int n); |
| 69 bool AddNum(uint64_t num, int base); // base must be 10 or 16. |
| 70 |
| 71 static const int kBufSize = 200; |
| 72 char* p_; |
| 73 char* end_; |
| 74 char buf_[kBufSize]; |
| 75 }; |
| 76 |
| 77 void Log(LogMode mode, const char* filename, int line, |
| 78 LogItem a, LogItem b, LogItem c, LogItem d) { |
| 79 Logger state; |
| 80 state.p_ = state.buf_; |
| 81 state.end_ = state.buf_ + sizeof(state.buf_); |
| 82 state.AddStr(filename, strlen(filename)) |
| 83 && state.AddStr(":", 1) |
| 84 && state.AddNum(line, 10) |
| 85 && state.AddStr("]", 1) |
| 86 && state.Add(a) |
| 87 && state.Add(b) |
| 88 && state.Add(c) |
| 89 && state.Add(d); |
| 90 |
| 91 // Teminate with newline |
| 92 if (state.p_ >= state.end_) { |
| 93 state.p_ = state.end_ - 1; |
74 } | 94 } |
75 write(STDERR_FILENO, buf, strlen(buf)); | 95 *state.p_ = '\n'; |
76 if (dump_stats) { | 96 state.p_++; |
| 97 |
| 98 int msglen = state.p_ - state.buf_; |
| 99 if (mode == kLog) { |
| 100 (*log_message_writer)(state.buf_, msglen); |
| 101 return; |
| 102 } |
| 103 |
| 104 bool first_crash = false; |
| 105 { |
| 106 SpinLockHolder l(&crash_lock); |
| 107 if (!crashed) { |
| 108 crashed = true; |
| 109 first_crash = true; |
| 110 } |
| 111 } |
| 112 |
| 113 (*log_message_writer)(state.buf_, msglen); |
| 114 if (first_crash && mode == kCrashWithStats) { |
77 MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize); | 115 MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize); |
78 write(STDERR_FILENO, stats_buffer, strlen(stats_buffer)); | 116 (*log_message_writer)(stats_buffer, strlen(stats_buffer)); |
79 } | 117 } |
80 | 118 |
81 abort(); | 119 abort(); |
82 } | 120 } |
83 | 121 |
84 void TCMalloc_CRASH(bool dump_stats, | 122 bool Logger::Add(const LogItem& item) { |
85 const char* filename, | 123 // Separate items with spaces |
86 int line_number, | 124 if (p_ < end_) { |
87 const char* format, ...) { | 125 *p_ = ' '; |
88 va_list ap; | 126 p_++; |
89 va_start(ap, format); | 127 } |
90 TCMalloc_CRASH_internal(dump_stats, filename, line_number, format, ap); | 128 |
91 va_end(ap); | 129 switch (item.tag_) { |
| 130 case LogItem::kStr: |
| 131 return AddStr(item.u_.str, strlen(item.u_.str)); |
| 132 case LogItem::kUnsigned: |
| 133 return AddNum(item.u_.unum, 10); |
| 134 case LogItem::kSigned: |
| 135 if (item.u_.snum < 0) { |
| 136 // The cast to uint64_t is intentionally before the negation |
| 137 // so that we do not attempt to negate -2^63. |
| 138 return AddStr("-", 1) |
| 139 && AddNum(- static_cast<uint64_t>(item.u_.snum), 10); |
| 140 } else { |
| 141 return AddNum(static_cast<uint64_t>(item.u_.snum), 10); |
| 142 } |
| 143 case LogItem::kPtr: |
| 144 return AddStr("0x", 2) |
| 145 && AddNum(reinterpret_cast<uintptr_t>(item.u_.ptr), 16); |
| 146 default: |
| 147 return false; |
| 148 } |
92 } | 149 } |
93 | 150 |
| 151 bool Logger::AddStr(const char* str, int n) { |
| 152 if (end_ - p_ < n) { |
| 153 return false; |
| 154 } else { |
| 155 memcpy(p_, str, n); |
| 156 p_ += n; |
| 157 return true; |
| 158 } |
| 159 } |
94 | 160 |
95 void TCMalloc_CrashReporter::PrintfAndDie(const char* format, ...) { | 161 bool Logger::AddNum(uint64_t num, int base) { |
96 va_list ap; | 162 static const char kDigits[] = "0123456789abcdef"; |
97 va_start(ap, format); | 163 char space[22]; // more than enough for 2^64 in smallest supported base (10) |
98 TCMalloc_CRASH_internal(dump_stats_, file_, line_, format, ap); | 164 char* end = space + sizeof(space); |
99 va_end(ap); | 165 char* pos = end; |
| 166 do { |
| 167 pos--; |
| 168 *pos = kDigits[num % base]; |
| 169 num /= base; |
| 170 } while (num > 0 && pos > space); |
| 171 return AddStr(pos, end - pos); |
100 } | 172 } |
101 | 173 |
| 174 } // end tcmalloc namespace |
| 175 |
102 void TCMalloc_Printer::printf(const char* format, ...) { | 176 void TCMalloc_Printer::printf(const char* format, ...) { |
103 if (left_ > 0) { | 177 if (left_ > 0) { |
104 va_list ap; | 178 va_list ap; |
105 va_start(ap, format); | 179 va_start(ap, format); |
106 const int r = perftools_vsnprintf(buf_, left_, format, ap); | 180 const int r = perftools_vsnprintf(buf_, left_, format, ap); |
107 va_end(ap); | 181 va_end(ap); |
108 if (r < 0) { | 182 if (r < 0) { |
109 // Perhaps an old glibc that returns -1 on truncation? | 183 // Perhaps an old glibc that returns -1 on truncation? |
110 left_ = 0; | 184 left_ = 0; |
111 } else if (r > left_) { | 185 } else if (r > left_) { |
112 // Truncation | 186 // Truncation |
113 left_ = 0; | 187 left_ = 0; |
114 } else { | 188 } else { |
115 left_ -= r; | 189 left_ -= r; |
116 buf_ += r; | 190 buf_ += r; |
117 } | 191 } |
118 } | 192 } |
119 } | 193 } |
OLD | NEW |