Skip to content

Commit

Permalink
[lldb] Introduce an always-on system log category/channel (llvm#108495)
Browse files Browse the repository at this point in the history
Add an "always on" log category and channel. Unlike other, existing log
channels, it is not exposed to users. The channel is meant to be used
sparsely and deliberately for logging high-value information to the
system log.

We have a similar concept in the downstream Swift fork and this has
proven to be extremely valuable. This is especially true on macOS where
system log messages are automatically captured as part of a sysdiagnose.
  • Loading branch information
JDevlieghere authored Oct 10, 2024
1 parent c042d8f commit c77b107
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 18 deletions.
19 changes: 19 additions & 0 deletions lldb/include/lldb/Host/Host.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ class ProcessInstanceInfo;
class ProcessInstanceInfoMatch;
typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;

// System log category and channel. This log channel is always enabled and
// therefore is supposed to be used sparsely. Use this log channel to log
// critical information that is expected to be relevant to the majority of bug
// reports.
enum class SystemLog : Log::MaskType {
System = Log::ChannelFlag<0>,
LLVM_MARK_AS_BITMASK_ENUM(System)
};

LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();

class LogChannelSystem {
public:
static void Initialize();
static void Terminate();
};

template <> Log::Channel &LogChannelFor<SystemLog>();

// Exit Type for inferior processes
struct WaitStatus {
enum Type : uint8_t {
Expand Down
11 changes: 6 additions & 5 deletions lldb/include/lldb/Utility/Log.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ class Log final {
void VAFormatf(llvm::StringRef file, llvm::StringRef function,
const char *format, va_list args);

void Enable(const std::shared_ptr<LogHandler> &handler_sp,
std::optional<MaskType> flags = std::nullopt,
uint32_t options = 0);

void Disable(std::optional<MaskType> flags = std::nullopt);

private:
Channel &m_channel;

Expand All @@ -297,11 +303,6 @@ class Log final {
return m_handler;
}

void Enable(const std::shared_ptr<LogHandler> &handler_sp, uint32_t options,
MaskType flags);

void Disable(MaskType flags);

bool Dump(llvm::raw_ostream &stream);

typedef llvm::StringMap<Log> ChannelMap;
Expand Down
3 changes: 3 additions & 0 deletions lldb/source/API/SystemInitializerFull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Target/ProcessTrace.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Version/Version.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetSelect.h"

Expand Down Expand Up @@ -83,6 +84,8 @@ llvm::Error SystemInitializerFull::Initialize() {
// Use the Debugger's LLDBAssert callback.
SetLLDBAssertCallback(Debugger::AssertCallback);

LLDB_LOG(GetLog(SystemLog::System), "{0}", GetVersion());

return llvm::Error::success();
}

Expand Down
16 changes: 16 additions & 0 deletions lldb/source/Host/common/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,22 @@ void Host::SystemLog(Severity severity, llvm::StringRef message) {
#endif
#endif

static constexpr Log::Category g_categories[] = {
{{"system"}, {"system log"}, SystemLog::System}};

static Log::Channel g_system_channel(g_categories, SystemLog::System);
static Log g_system_log(g_system_channel);

template <> Log::Channel &lldb_private::LogChannelFor<SystemLog>() {
return g_system_channel;
}

void LogChannelSystem::Initialize() {
g_system_log.Enable(std::make_shared<SystemLogHandler>());
}

void LogChannelSystem::Terminate() { g_system_log.Disable(); }

#if !defined(__APPLE__) && !defined(_WIN32)
static thread_result_t
MonitorChildProcessThreadFunction(::pid_t pid,
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Host/common/HostInfoBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr;
void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) {
g_shlib_dir_helper = helper;
g_fields = new HostInfoBaseFields();
LogChannelSystem::Initialize();
}

void HostInfoBase::Terminate() {
LogChannelSystem::Terminate();
g_shlib_dir_helper = nullptr;
delete g_fields;
g_fields = nullptr;
Expand Down
34 changes: 21 additions & 13 deletions lldb/source/Utility/Log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,22 +93,28 @@ Log::MaskType Log::GetFlags(llvm::raw_ostream &stream,
}

void Log::Enable(const std::shared_ptr<LogHandler> &handler_sp,
uint32_t options, Log::MaskType flags) {
std::optional<Log::MaskType> flags, uint32_t options) {
llvm::sys::ScopedWriter lock(m_mutex);

MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed);
if (mask | flags) {
if (!flags)
flags = m_channel.default_flags;

MaskType mask = m_mask.fetch_or(*flags, std::memory_order_relaxed);
if (mask | *flags) {
m_options.store(options, std::memory_order_relaxed);
m_handler = handler_sp;
m_channel.log_ptr.store(this, std::memory_order_relaxed);
}
}

void Log::Disable(Log::MaskType flags) {
void Log::Disable(std::optional<Log::MaskType> flags) {
llvm::sys::ScopedWriter lock(m_mutex);

MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
if (!(mask & ~flags)) {
if (!flags)
flags = std::numeric_limits<MaskType>::max();

MaskType mask = m_mask.fetch_and(~(*flags), std::memory_order_relaxed);
if (!(mask & ~(*flags))) {
m_handler.reset();
m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
}
Expand Down Expand Up @@ -230,10 +236,11 @@ bool Log::EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
return false;
}
MaskType flags = categories.empty()
? iter->second.m_channel.default_flags
: GetFlags(error_stream, *iter, categories);
iter->second.Enable(log_handler_sp, log_options, flags);

auto flags = categories.empty() ? std::optional<MaskType>{}
: GetFlags(error_stream, *iter, categories);

iter->second.Enable(log_handler_sp, flags, log_options);
return true;
}

Expand All @@ -245,9 +252,10 @@ bool Log::DisableLogChannel(llvm::StringRef channel,
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
return false;
}
MaskType flags = categories.empty()
? std::numeric_limits<MaskType>::max()
: GetFlags(error_stream, *iter, categories);

auto flags = categories.empty() ? std::optional<MaskType>{}
: GetFlags(error_stream, *iter, categories);

iter->second.Disable(flags);
return true;
}
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/Shell/Host/TestSytemLogChannel.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RUN: %lldb -o 'log list' -o 'log disable system' 2>&1 | FileCheck %s
CHECK-NOT: Logging categories for 'system'
CHECK: Invalid log channel 'system'

0 comments on commit c77b107

Please sign in to comment.