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 <gperftools/malloc_extension.h> | 43 #include <google/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 // Variables for storing crash output. Allocated statically since we | 49 void TCMalloc_MESSAGE(const char* filename, |
50 // may not be able to heap-allocate while crashing. | 50 int line_number, |
51 static SpinLock crash_lock(base::LINKER_INITIALIZED); | 51 const char* format, ...) { |
52 static bool crashed = false; | 52 char buf[kLogBufSize]; |
| 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 |
53 static const int kStatsBufferSize = 16 << 10; | 63 static const int kStatsBufferSize = 16 << 10; |
54 static char stats_buffer[kStatsBufferSize] = { 0 }; | 64 static char stats_buffer[kStatsBufferSize] = { 0 }; |
55 | 65 |
56 namespace tcmalloc { | 66 static void TCMalloc_CRASH_internal(bool dump_stats, |
57 | 67 const char* filename, |
58 static void WriteMessage(const char* msg, int length) { | 68 int line_number, |
59 write(STDERR_FILENO, msg, length); | 69 const char* format, va_list ap) { |
60 } | 70 char buf[kLogBufSize]; |
61 | 71 const int n = snprintf(buf, sizeof(buf), "%s:%d] ", filename, line_number); |
62 void (*log_message_writer)(const char* msg, int length) = WriteMessage; | 72 if (n < kLogBufSize) { |
63 | 73 perftools_vsnprintf(buf + n, kLogBufSize - n, format, ap); |
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; | |
94 } | 74 } |
95 *state.p_ = '\n'; | 75 write(STDERR_FILENO, buf, strlen(buf)); |
96 state.p_++; | 76 if (dump_stats) { |
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) { | |
115 MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize); | 77 MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize); |
116 (*log_message_writer)(stats_buffer, strlen(stats_buffer)); | 78 write(STDERR_FILENO, stats_buffer, strlen(stats_buffer)); |
117 } | 79 } |
118 | 80 |
119 abort(); | 81 abort(); |
120 } | 82 } |
121 | 83 |
122 bool Logger::Add(const LogItem& item) { | 84 void TCMalloc_CRASH(bool dump_stats, |
123 // Separate items with spaces | 85 const char* filename, |
124 if (p_ < end_) { | 86 int line_number, |
125 *p_ = ' '; | 87 const char* format, ...) { |
126 p_++; | 88 va_list ap; |
127 } | 89 va_start(ap, format); |
128 | 90 TCMalloc_CRASH_internal(dump_stats, filename, line_number, format, ap); |
129 switch (item.tag_) { | 91 va_end(ap); |
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 } | |
149 } | 92 } |
150 | 93 |
151 bool Logger::AddStr(const char* str, int n) { | 94 |
152 if (end_ - p_ < n) { | 95 void TCMalloc_CrashReporter::PrintfAndDie(const char* format, ...) { |
153 return false; | 96 va_list ap; |
154 } else { | 97 va_start(ap, format); |
155 memcpy(p_, str, n); | 98 TCMalloc_CRASH_internal(dump_stats_, file_, line_, format, ap); |
156 p_ += n; | 99 va_end(ap); |
157 return true; | |
158 } | |
159 } | 100 } |
160 | 101 |
161 bool Logger::AddNum(uint64_t num, int base) { | |
162 static const char kDigits[] = "0123456789abcdef"; | |
163 char space[22]; // more than enough for 2^64 in smallest supported base (10) | |
164 char* end = space + sizeof(space); | |
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); | |
172 } | |
173 | |
174 } // end tcmalloc namespace | |
175 | |
176 void TCMalloc_Printer::printf(const char* format, ...) { | 102 void TCMalloc_Printer::printf(const char* format, ...) { |
177 if (left_ > 0) { | 103 if (left_ > 0) { |
178 va_list ap; | 104 va_list ap; |
179 va_start(ap, format); | 105 va_start(ap, format); |
180 const int r = perftools_vsnprintf(buf_, left_, format, ap); | 106 const int r = perftools_vsnprintf(buf_, left_, format, ap); |
181 va_end(ap); | 107 va_end(ap); |
182 if (r < 0) { | 108 if (r < 0) { |
183 // Perhaps an old glibc that returns -1 on truncation? | 109 // Perhaps an old glibc that returns -1 on truncation? |
184 left_ = 0; | 110 left_ = 0; |
185 } else if (r > left_) { | 111 } else if (r > left_) { |
186 // Truncation | 112 // Truncation |
187 left_ = 0; | 113 left_ = 0; |
188 } else { | 114 } else { |
189 left_ -= r; | 115 left_ -= r; |
190 buf_ += r; | 116 buf_ += r; |
191 } | 117 } |
192 } | 118 } |
193 } | 119 } |
OLD | NEW |