00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/base/internal/raw_logging.h"
00016
00017 #include <stddef.h>
00018 #include <cstdarg>
00019 #include <cstdio>
00020 #include <cstdlib>
00021 #include <cstring>
00022
00023 #include "absl/base/attributes.h"
00024 #include "absl/base/config.h"
00025 #include "absl/base/internal/atomic_hook.h"
00026 #include "absl/base/log_severity.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
00039 defined(__Fuchsia__) || defined(__native_client__) || \
00040 defined(__EMSCRIPTEN__)
00041 #include <unistd.h>
00042
00043
00044 #define ABSL_HAVE_POSIX_WRITE 1
00045 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
00046 #else
00047 #undef ABSL_HAVE_POSIX_WRITE
00048 #endif
00049
00050
00051
00052
00053 #if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)
00054 #include <sys/syscall.h>
00055 #define ABSL_HAVE_SYSCALL_WRITE 1
00056 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
00057 #else
00058 #undef ABSL_HAVE_SYSCALL_WRITE
00059 #endif
00060
00061 #ifdef _WIN32
00062 #include <io.h>
00063
00064 #define ABSL_HAVE_RAW_IO 1
00065 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
00066 #else
00067 #undef ABSL_HAVE_RAW_IO
00068 #endif
00069
00070
00071
00072
00073
00074 ABSL_CONST_INIT static absl::base_internal::AtomicHook<
00075 absl::raw_logging_internal::LogPrefixHook> log_prefix_hook;
00076 ABSL_CONST_INIT static absl::base_internal::AtomicHook<
00077 absl::raw_logging_internal::AbortHook> abort_hook;
00078
00079 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
00080 static const char kTruncated[] = " ... (message truncated)\n";
00081
00082
00083
00084
00085
00086 inline static bool VADoRawLog(char** buf, int* size, const char* format,
00087 va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
00088 inline static bool VADoRawLog(char** buf, int* size,
00089 const char* format, va_list ap) {
00090 int n = vsnprintf(*buf, *size, format, ap);
00091 bool result = true;
00092 if (n < 0 || n > *size) {
00093 result = false;
00094 if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
00095 n = *size - sizeof(kTruncated);
00096 } else {
00097 n = 0;
00098 }
00099 }
00100 *size -= n;
00101 *buf += n;
00102 return result;
00103 }
00104 #endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED
00105
00106 static constexpr int kLogBufSize = 3000;
00107
00108 namespace {
00109
00110
00111
00112
00113
00114
00115
00116 bool DoRawLog(char** buf, int* size, const char* format, ...)
00117 ABSL_PRINTF_ATTRIBUTE(3, 4);
00118 bool DoRawLog(char** buf, int* size, const char* format, ...) {
00119 va_list ap;
00120 va_start(ap, format);
00121 int n = vsnprintf(*buf, *size, format, ap);
00122 va_end(ap);
00123 if (n < 0 || n > *size) return false;
00124 *size -= n;
00125 *buf += n;
00126 return true;
00127 }
00128
00129 void RawLogVA(absl::LogSeverity severity, const char* file, int line,
00130 const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
00131 void RawLogVA(absl::LogSeverity severity, const char* file, int line,
00132 const char* format, va_list ap) {
00133 char buffer[kLogBufSize];
00134 char* buf = buffer;
00135 int size = sizeof(buffer);
00136 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
00137 bool enabled = true;
00138 #else
00139 bool enabled = false;
00140 #endif
00141
00142 #ifdef ABSL_MIN_LOG_LEVEL
00143 if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
00144 severity < absl::LogSeverity::kFatal) {
00145 enabled = false;
00146 }
00147 #endif
00148
00149 auto log_prefix_hook_ptr = log_prefix_hook.Load();
00150 if (log_prefix_hook_ptr) {
00151 enabled = log_prefix_hook_ptr(severity, file, line, &buf, &size);
00152 } else {
00153 if (enabled) {
00154 DoRawLog(&buf, &size, "[%s : %d] RAW: ", file, line);
00155 }
00156 }
00157 const char* const prefix_end = buf;
00158
00159 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
00160 if (enabled) {
00161 bool no_chop = VADoRawLog(&buf, &size, format, ap);
00162 if (no_chop) {
00163 DoRawLog(&buf, &size, "\n");
00164 } else {
00165 DoRawLog(&buf, &size, "%s", kTruncated);
00166 }
00167 absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
00168 }
00169 #else
00170 static_cast<void>(format);
00171 static_cast<void>(ap);
00172 #endif
00173
00174
00175
00176 if (severity == absl::LogSeverity::kFatal) {
00177 abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize);
00178 abort();
00179 }
00180 }
00181
00182 }
00183
00184 namespace absl {
00185 namespace raw_logging_internal {
00186 void SafeWriteToStderr(const char *s, size_t len) {
00187 #if defined(ABSL_HAVE_SYSCALL_WRITE)
00188 syscall(SYS_write, STDERR_FILENO, s, len);
00189 #elif defined(ABSL_HAVE_POSIX_WRITE)
00190 write(STDERR_FILENO, s, len);
00191 #elif defined(ABSL_HAVE_RAW_IO)
00192 _write( 2, s, len);
00193 #else
00194
00195 (void) s;
00196 (void) len;
00197 #endif
00198 }
00199
00200 void RawLog(absl::LogSeverity severity, const char* file, int line,
00201 const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
00202 void RawLog(absl::LogSeverity severity, const char* file, int line,
00203 const char* format, ...) {
00204 va_list ap;
00205 va_start(ap, format);
00206 RawLogVA(severity, file, line, format, ap);
00207 va_end(ap);
00208 }
00209
00210
00211
00212
00213
00214 static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
00215 int line, const std::string& message) {
00216 RawLog(severity, file, line, "%s", message.c_str());
00217 }
00218
00219 bool RawLoggingFullySupported() {
00220 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
00221 return true;
00222 #else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
00223 return false;
00224 #endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
00225 }
00226
00227 ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
00228 internal_log_function(DefaultInternalLog);
00229
00230 void RegisterInternalLogFunction(InternalLogFunction func) {
00231 internal_log_function.Store(func);
00232 }
00233
00234 }
00235 }