tvl-depot/absl/base/internal/raw_logging.cc
Abseil Team 02687955b7 Export of internal Abseil changes.
--
898e99cae89ca4cc27f86f719148f020d521dd58 by Abseil Team <absl-team@google.com>:

Update comment.

PiperOrigin-RevId: 204323401

--
b9d14db8b8a9dfb0e1cfb5967aaa0de1c4e94c42 by Abseil Team <absl-team@google.com>:

Internal change

PiperOrigin-RevId: 204178059

--
f3b5a667611a588aa06fea9168e997ef5cffa7ac by Abseil Team <absl-team@google.com>:

Fix a potential reinterpret_cast compile error in absl::InlinedVector

The current code will trigger a reinterpret_cast error enhanced by llvm r336738.

PiperOrigin-RevId: 204131536

--
cc87d7a8302ad4471c1a25781d6ec19c2ce1524e by Abseil Team <absl-team@google.com>:

Internal change.

PiperOrigin-RevId: 203979040

--
bc5cae3cfc72af1d3e786d5a3b59a47e205afec9 by Gennadiy Rozental <rogeeff@google.com>:

Internal: add internal logging hooks

PiperOrigin-RevId: 203850605

--
503655c248f557f677c920078613522b010e73c8 by Derek Mauro <dmauro@google.com>:

Cleanup stacktrace_config.h

Instead of listing the platforms that aren't supported, list the ones
we do support, and fallback to stacktrace_unimplemented-inl.inc at the
end. Previously any platform that wasn't listed gets "#error Not supported yet".

GitHub issue #135

PiperOrigin-RevId: 203823079

--
cb69925c4cacc14558cf103a09f218c37f466a16 by Abseil Team <absl-team@google.com>:

Fix a minor typo in absl::variant documentation.

PiperOrigin-RevId: 203679877

--
23a0e4db10039011fa5fd879fb73d2f2bbd17301 by Abseil Team <absl-team@google.com>:

Format .bzl files with buildifier

PiperOrigin-RevId: 203461813

--
1ad02616bdb715dfdc7f1a73313e383f4ededa03 by Abseil Team <absl-team@google.com>:

Make the absl::SleepFor() tests treat any successful retry within
a 48x deadline as a total success, thereby reducing flakiness.

PiperOrigin-RevId: 203401603

--
b3dccbbc6563ea0173527076a3fff21433d48f47 by Abseil Team <absl-team@google.com>:

Replace config_setting.values{"compiler"} with config_setting.flag_values{"@bazel_tools//tools/cpp:compiler"}

Due to changes in Bazel we need to change the way "compiler" is specified in config_setting. This will not change the behavior of the config_setting itself.

PiperOrigin-RevId: 203345693

--
170f1692537460a4ba1756d34852275899c2339b by Matt Armstrong <marmstrong@google.com>:

Address test flakiness in the TimeoutTest.

The basic idea is to loop forever until the expected
scheduling delays are observed (within reasonable bounds),
and only then assert the other invariants.

PiperOrigin-RevId: 203188162
GitOrigin-RevId: 898e99cae89ca4cc27f86f719148f020d521dd58
Change-Id: Ie853ec050afa3a04c519393afe666bc03e11dc87
2018-07-12 14:35:25 -04:00

234 lines
7.4 KiB
C++

// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/base/internal/raw_logging.h"
#include <stddef.h>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/log_severity.h"
// We know how to perform low-level writes to stderr in POSIX and Windows. For
// these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED.
// Much of raw_logging.cc becomes a no-op when we can't output messages,
// although a FATAL ABSL_RAW_LOG message will still abort the process.
// ABSL_HAVE_POSIX_WRITE is defined when the platform provides posix write()
// (as from unistd.h)
//
// This preprocessor token is also defined in raw_io.cc. If you need to copy
// this, consider moving both to config.h instead.
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(__Fuchsia__) || defined(__native_client__)
#include <unistd.h>
#define ABSL_HAVE_POSIX_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_POSIX_WRITE
#endif
// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall
// syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);
// for low level operations that want to avoid libc.
#if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)
#include <sys/syscall.h>
#define ABSL_HAVE_SYSCALL_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_SYSCALL_WRITE
#endif
#ifdef _WIN32
#include <io.h>
#define ABSL_HAVE_RAW_IO 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
#else
#undef ABSL_HAVE_RAW_IO
#endif
// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
// Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
// whitelisted set of platforms for which we expect not to be able to raw log.
ABSL_CONST_INIT static absl::base_internal::AtomicHook<
absl::raw_logging_internal::LogPrefixHook> log_prefix_hook;
ABSL_CONST_INIT static absl::base_internal::AtomicHook<
absl::raw_logging_internal::AbortHook> abort_hook;
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
static const char kTruncated[] = " ... (message truncated)\n";
// sprintf the format to the buffer, adjusting *buf and *size to reflect the
// consumed bytes, and return whether the message fit without truncation. If
// truncation occurred, if possible leave room in the buffer for the message
// kTruncated[].
inline static bool VADoRawLog(char** buf, int* size, const char* format,
va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
inline static bool VADoRawLog(char** buf, int* size,
const char* format, va_list ap) {
int n = vsnprintf(*buf, *size, format, ap);
bool result = true;
if (n < 0 || n > *size) {
result = false;
if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
n = *size - sizeof(kTruncated); // room for truncation message
} else {
n = 0; // no room for truncation message
}
}
*size -= n;
*buf += n;
return result;
}
#endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED
static constexpr int kLogBufSize = 3000;
namespace {
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
// Helper for RawLog below.
// *DoRawLog writes to *buf of *size and move them past the written portion.
// It returns true iff there was no overflow or error.
bool DoRawLog(char** buf, int* size, const char* format, ...)
ABSL_PRINTF_ATTRIBUTE(3, 4);
bool DoRawLog(char** buf, int* size, const char* format, ...) {
va_list ap;
va_start(ap, format);
int n = vsnprintf(*buf, *size, format, ap);
va_end(ap);
if (n < 0 || n > *size) return false;
*size -= n;
*buf += n;
return true;
}
void RawLogVA(absl::LogSeverity severity, const char* file, int line,
const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
void RawLogVA(absl::LogSeverity severity, const char* file, int line,
const char* format, va_list ap) {
char buffer[kLogBufSize];
char* buf = buffer;
int size = sizeof(buffer);
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
bool enabled = true;
#else
bool enabled = false;
#endif
#ifdef ABSL_MIN_LOG_LEVEL
if (static_cast<int>(severity) < ABSL_MIN_LOG_LEVEL &&
severity < absl::LogSeverity::kFatal) {
enabled = false;
}
#endif
auto log_prefix_hook_ptr = log_prefix_hook.Load();
if (log_prefix_hook_ptr) {
enabled = log_prefix_hook_ptr(severity, file, line, &buf, &size);
} else {
if (enabled) {
DoRawLog(&buf, &size, "[%s : %d] RAW: ", file, line);
}
}
const char* const prefix_end = buf;
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
if (enabled) {
bool no_chop = VADoRawLog(&buf, &size, format, ap);
if (no_chop) {
DoRawLog(&buf, &size, "\n");
} else {
DoRawLog(&buf, &size, "%s", kTruncated);
}
absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
}
#else
static_cast<void>(format);
static_cast<void>(ap);
#endif
// Abort the process after logging a FATAL message, even if the output itself
// was suppressed.
if (severity == absl::LogSeverity::kFatal) {
abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize);
abort();
}
}
} // namespace
namespace absl {
namespace raw_logging_internal {
void SafeWriteToStderr(const char *s, size_t len) {
#if defined(ABSL_HAVE_SYSCALL_WRITE)
syscall(SYS_write, STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_POSIX_WRITE)
write(STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_RAW_IO)
_write(/* stderr */ 2, s, len);
#else
// stderr logging unsupported on this platform
(void) s;
(void) len;
#endif
}
void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) {
va_list ap;
va_start(ap, format);
RawLogVA(severity, file, line, format, ap);
va_end(ap);
}
// Non-formatting version of RawLog().
//
// TODO(gfalcon): When string_view no longer depends on base, change this
// interface to take its message as a string_view instead.
static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
int line, const std::string& message) {
RawLog(severity, file, line, "%s", message.c_str());
}
bool RawLoggingFullySupported() {
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
return true;
#else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
return false;
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}
ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
internal_log_function(DefaultInternalLog);
void RegisterInternalLogFunction(InternalLogFunction func) {
internal_log_function.Store(func);
}
} // namespace raw_logging_internal
} // namespace absl