Commit 322ae242 by Abseil Team Committed by Andy Getz

Export of internal Abseil changes

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

Clarify the "Potential Mutex deadlock" reason message.

PiperOrigin-RevId: 351367862

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

Print CPU number is fault handler.

This CL adds code to print CPU number inside the fault handler.  This is only supported on Linux.  The CPU number is also a hint only.  There is no guarantee that it is indeed the CPU on which a fault happened.

PiperOrigin-RevId: 351238373

--
66a9c8e44b5744fec1ca0d7b8db7e1d50772d9a2 by Samuel Benzaquen <sbenza@google.com>:

Add better error message for ODR violations of flags.

PiperOrigin-RevId: 351197423

--
6efd1efb341563148dd43255aaa4bf959dfd9554 by Chris Kennelly <ckennelly@google.com>:

Assume bitwise builtins are available on GCC.

These are long-standing builtins but are not consistently detected by
ABSL_HAVE_BUILTIN.

PiperOrigin-RevId: 350814036
GitOrigin-RevId: 1609589925459c2c0b2a17912c0d65227f709db9
Change-Id: Ied3fd2f135187f2c316b403fba45f3bbaea54138
parent 62ce712e
......@@ -379,6 +379,15 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1
#endif
// ABSL_HAVE_SCHED_GETCPU
//
// Checks whether sched_getcpu is available.
#ifdef ABSL_HAVE_SCHED_GETCPU
#error ABSL_HAVE_SCHED_GETCPU cannot be directly set
#elif defined(__linux__)
#define ABSL_HAVE_SCHED_GETCPU 1
#endif
// ABSL_HAVE_SCHED_YIELD
//
// Checks whether the platform implements sched_yield(2) as defined in
......
......@@ -21,6 +21,7 @@
#ifdef _WIN32
#include <windows.h>
#else
#include <sched.h>
#include <unistd.h>
#endif
......@@ -219,17 +220,24 @@ static void WriteToStderr(const char* data) {
absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
}
static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) {
char buf[64];
static void WriteSignalMessage(int signo, int cpu,
void (*writerfn)(const char*)) {
char buf[96];
char on_cpu[32] = {0};
if (cpu != -1) {
snprintf(on_cpu, sizeof(on_cpu), " on cpu %d", cpu);
}
const char* const signal_string =
debugging_internal::FailureSignalToString(signo);
if (signal_string != nullptr && signal_string[0] != '\0') {
snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n",
snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n",
signal_string,
static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
on_cpu);
} else {
snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n",
signo, static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
signo, static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
on_cpu);
}
writerfn(buf);
}
......@@ -269,10 +277,10 @@ ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace(
// Called by AbslFailureSignalHandler() to write the failure info. It is
// called once with writerfn set to WriteToStderr() and then possibly
// with writerfn set to the user provided function.
static void WriteFailureInfo(int signo, void* ucontext,
static void WriteFailureInfo(int signo, void* ucontext, int cpu,
void (*writerfn)(const char*)) {
WriterFnStruct writerfn_struct{writerfn};
WriteSignalMessage(signo, writerfn);
WriteSignalMessage(signo, cpu, writerfn);
WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,
&writerfn_struct);
}
......@@ -334,6 +342,14 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
}
}
// Increase the chance that the CPU we report was the same CPU on which the
// signal was received by doing this as early as possible, i.e. after
// verifying that this is not a recursive signal handler invocation.
int my_cpu = -1;
#ifdef ABSL_HAVE_SCHED_GETCPU
my_cpu = sched_getcpu();
#endif
#ifdef ABSL_HAVE_ALARM
// Set an alarm to abort the program in case this code hangs or deadlocks.
if (fsh_options.alarm_on_failure_secs > 0) {
......@@ -344,12 +360,12 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
#endif
// First write to stderr.
WriteFailureInfo(signo, ucontext, WriteToStderr);
WriteFailureInfo(signo, ucontext, my_cpu, WriteToStderr);
// Riskier code (because it is less likely to be async-signal-safe)
// goes after this point.
if (fsh_options.writerfn != nullptr) {
WriteFailureInfo(signo, ucontext, fsh_options.writerfn);
WriteFailureInfo(signo, ucontext, my_cpu, fsh_options.writerfn);
}
if (fsh_options.call_previous_handler) {
......
......@@ -122,6 +122,12 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
"*** ", absl::debugging_internal::FailureSignalToString(signo),
" received at ")));
// On platforms where it is possible to get the current CPU, the
// CPU number is also logged. Check that it is present in output.
#if defined(__linux__)
EXPECT_THAT(error_line, testing::HasSubstr(" on cpu "));
#endif
if (absl::debugging_internal::StackTraceWorksForTest()) {
std::getline(error_output, error_line);
EXPECT_THAT(error_line, StartsWith("PC: "));
......
......@@ -302,12 +302,14 @@ ABSL_NAMESPACE_END
#define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
#define ABSL_FLAG_IMPL_FILENAME() ""
#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
nullptr)
#else
#define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
#define ABSL_FLAG_IMPL_FILENAME() __FILE__
#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
__FILE__)
#endif
// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
......
......@@ -177,7 +177,7 @@ bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2), nullptr)
.OnUpdate(TestCallback);
EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
......
......@@ -721,8 +721,9 @@ struct FlagRegistrarEmpty {};
template <typename T, bool do_register>
class FlagRegistrar {
public:
explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
explicit FlagRegistrar(Flag<T>& flag, const char* filename) : flag_(flag) {
if (do_register)
flags_internal::RegisterCommandLineFlag(flag_.impl_, filename);
}
FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
......
......@@ -36,7 +36,7 @@ void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
//-----------------------------------------------------------------------------
bool RegisterCommandLineFlag(CommandLineFlag&);
bool RegisterCommandLineFlag(CommandLineFlag&, const char* filename);
void FinalizeRegistry();
......
......@@ -50,7 +50,7 @@ class FlagRegistry {
~FlagRegistry() = default;
// Store a flag in this registry. Takes ownership of *flag.
void RegisterFlag(CommandLineFlag& flag);
void RegisterFlag(CommandLineFlag& flag, const char* filename);
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
......@@ -110,7 +110,20 @@ CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
return it != flags_.end() ? it->second : nullptr;
}
void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
void FlagRegistry::RegisterFlag(CommandLineFlag& flag, const char* filename) {
if (filename != nullptr &&
flag.Filename() != GetUsageConfig().normalize_filename(filename)) {
flags_internal::ReportUsageError(
absl::StrCat(
"Inconsistency between flag object and registration for flag '",
flag.Name(),
"', likely due to duplicate flags or an ODR violation. Relevant "
"files: ",
flag.Filename(), " and ", filename),
true);
std::exit(1);
}
FlagRegistryLock registry_lock(*this);
std::pair<FlagIterator, bool> ins =
......@@ -175,8 +188,8 @@ void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
// --------------------------------------------------------------------
bool RegisterCommandLineFlag(CommandLineFlag& flag) {
FlagRegistry::GlobalRegistry().RegisterFlag(flag);
bool RegisterCommandLineFlag(CommandLineFlag& flag, const char* filename) {
FlagRegistry::GlobalRegistry().RegisterFlag(flag, filename);
return true;
}
......@@ -266,7 +279,7 @@ void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
auto* flag = ::new (static_cast<void*>(buf))
flags_internal::RetiredFlagObj(name, type_id);
FlagRegistry::GlobalRegistry().RegisterFlag(*flag);
FlagRegistry::GlobalRegistry().RegisterFlag(*flag, nullptr);
}
// --------------------------------------------------------------------
......
......@@ -560,6 +560,14 @@ TEST(IntegralPowersOfTwo, Width) {
}
}
// On GCC and Clang, anticiapte that implementations will be constexpr
#if defined(__GNUC__)
static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT,
"popcount should be constexpr");
static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CLZ, "clz should be constexpr");
static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CTZ, "ctz should be constexpr");
#endif
} // namespace
ABSL_NAMESPACE_END
} // namespace absl
......@@ -28,8 +28,15 @@
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#if ABSL_HAVE_BUILTIN(__builtin_popcountl) && \
ABSL_HAVE_BUILTIN(__builtin_popcountll)
#if defined(__GNUC__) && !defined(__clang__)
// GCC
#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1
#else
#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x)
#endif
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \
ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr
#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1
#else
......@@ -37,7 +44,8 @@
#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0
#endif
#if ABSL_HAVE_BUILTIN(__builtin_clz) && ABSL_HAVE_BUILTIN(__builtin_clzll)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \
ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr
#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1
#else
......@@ -45,7 +53,8 @@
#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0
#endif
#if ABSL_HAVE_BUILTIN(__builtin_ctz) && ABSL_HAVE_BUILTIN(__builtin_ctzll)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \
ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr
#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1
#else
......@@ -85,7 +94,7 @@ ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
Popcount32(uint32_t x) noexcept {
#if ABSL_HAVE_BUILTIN(__builtin_popcount)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount)
static_assert(sizeof(unsigned int) == sizeof(x),
"__builtin_popcount does not take 32-bit arg");
return __builtin_popcount(x);
......@@ -98,7 +107,7 @@ Popcount32(uint32_t x) noexcept {
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
Popcount64(uint64_t x) noexcept {
#if ABSL_HAVE_BUILTIN(__builtin_popcountll)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
"__builtin_popcount does not take 64-bit arg");
return __builtin_popcountll(x);
......@@ -122,7 +131,7 @@ Popcount(T x) noexcept {
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
CountLeadingZeroes32(uint32_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_clz)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz)
// Use __builtin_clz, which uses the following instructions:
// x86: bsr, lzcnt
// ARM64: clz
......@@ -169,7 +178,7 @@ CountLeadingZeroes16(uint16_t x) {
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
CountLeadingZeroes64(uint64_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_clzll)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
// Use __builtin_clzll, which uses the following instructions:
// x86: bsr, lzcnt
// ARM64: clz
......@@ -240,7 +249,7 @@ CountLeadingZeroes(T x) {
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
CountTrailingZeroesNonzero32(uint32_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_ctz)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz)
static_assert(sizeof(unsigned int) == sizeof(x),
"__builtin_ctz does not take 32-bit arg");
return __builtin_ctz(x);
......@@ -262,7 +271,7 @@ CountTrailingZeroesNonzero32(uint32_t x) {
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
CountTrailingZeroesNonzero64(uint64_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_ctzll)
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
"__builtin_ctzll does not take 64-bit arg");
return __builtin_ctzll(x);
......
......@@ -1372,7 +1372,9 @@ static GraphId DeadlockCheck(Mutex *mu) {
len += static_cast<int>(strlen(&b->buf[len]));
}
}
ABSL_RAW_LOG(ERROR, "Acquiring %p Mutexes held: %s",
ABSL_RAW_LOG(ERROR,
"Acquiring absl::Mutex %p while holding %s; a cycle in the "
"historical lock ordering graph has been observed",
static_cast<void *>(mu), b->buf);
ABSL_RAW_LOG(ERROR, "Cycle: ");
int path_len = deadlock_graph->FindPath(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment