Skip to content

Commit 98f1b5e

Browse files
committed
[lldb] Introduce an always-on system log category/channel
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. This patch revives https://reviews.llvm.org/D135621 although the purpose is slightly different (logging to the system log rather than to a ring buffer dumped as part of the diagnostics). This patch addresses all the remaining outstanding comments.
1 parent ee0e17a commit 98f1b5e

File tree

7 files changed

+70
-18
lines changed

7 files changed

+70
-18
lines changed

lldb/include/lldb/Host/Host.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,25 @@ class ProcessInstanceInfo;
3131
class ProcessInstanceInfoMatch;
3232
typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
3333

34+
// System log category and channel. This log channel is always enabled and
35+
// therefore is supposed to be used sparsely. Use this log channel to log
36+
// critical information that is expected to be relevant to the majority of bug
37+
// reports.
38+
enum class SystemLog : Log::MaskType {
39+
System = Log::ChannelFlag<0>,
40+
LLVM_MARK_AS_BITMASK_ENUM(System)
41+
};
42+
43+
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
44+
45+
class LogChannelSystem {
46+
public:
47+
static void Initialize();
48+
static void Terminate();
49+
};
50+
51+
template <> Log::Channel &LogChannelFor<SystemLog>();
52+
3453
// Exit Type for inferior processes
3554
struct WaitStatus {
3655
enum Type : uint8_t {

lldb/include/lldb/Utility/Log.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ class Log final {
272272
void VAFormatf(llvm::StringRef file, llvm::StringRef function,
273273
const char *format, va_list args);
274274

275+
void Enable(const std::shared_ptr<LogHandler> &handler_sp,
276+
std::optional<MaskType> flags = std::nullopt,
277+
uint32_t options = 0);
278+
279+
void Disable(std::optional<MaskType> flags = std::nullopt);
280+
275281
private:
276282
Channel &m_channel;
277283

@@ -297,11 +303,6 @@ class Log final {
297303
return m_handler;
298304
}
299305

300-
void Enable(const std::shared_ptr<LogHandler> &handler_sp, uint32_t options,
301-
MaskType flags);
302-
303-
void Disable(MaskType flags);
304-
305306
bool Dump(llvm::raw_ostream &stream);
306307

307308
typedef llvm::StringMap<Log> ChannelMap;

lldb/source/API/SystemInitializerFull.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "lldb/Interpreter/CommandInterpreter.h"
1818
#include "lldb/Target/ProcessTrace.h"
1919
#include "lldb/Utility/Timer.h"
20+
#include "lldb/Version/Version.h"
2021
#include "llvm/Support/CommandLine.h"
2122
#include "llvm/Support/TargetSelect.h"
2223

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

87+
LLDB_LOG(GetLog(SystemLog::System), "{0}", GetVersion());
88+
8689
return llvm::Error::success();
8790
}
8891

lldb/source/Host/common/Host.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,22 @@ void Host::SystemLog(Severity severity, llvm::StringRef message) {
125125
#endif
126126
#endif
127127

128+
static constexpr Log::Category g_categories[] = {
129+
{{"system"}, {"system log"}, SystemLog::System}};
130+
131+
static Log::Channel g_system_channel(g_categories, SystemLog::System);
132+
static Log g_system_log(g_system_channel);
133+
134+
template <> Log::Channel &lldb_private::LogChannelFor<SystemLog>() {
135+
return g_system_channel;
136+
}
137+
138+
void LogChannelSystem::Initialize() {
139+
g_system_log.Enable(std::make_shared<SystemLogHandler>());
140+
}
141+
142+
void LogChannelSystem::Terminate() { g_system_log.Disable(); }
143+
128144
#if !defined(__APPLE__) && !defined(_WIN32)
129145
static thread_result_t
130146
MonitorChildProcessThreadFunction(::pid_t pid,

lldb/source/Host/common/HostInfoBase.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr;
7676
void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) {
7777
g_shlib_dir_helper = helper;
7878
g_fields = new HostInfoBaseFields();
79+
LogChannelSystem::Initialize();
7980
}
8081

8182
void HostInfoBase::Terminate() {
83+
LogChannelSystem::Terminate();
8284
g_shlib_dir_helper = nullptr;
8385
delete g_fields;
8486
g_fields = nullptr;

lldb/source/Utility/Log.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,28 @@ Log::MaskType Log::GetFlags(llvm::raw_ostream &stream,
9393
}
9494

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

99-
MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed);
100-
if (mask | flags) {
99+
if (!flags)
100+
flags = m_channel.default_flags;
101+
102+
MaskType mask = m_mask.fetch_or(*flags, std::memory_order_relaxed);
103+
if (mask | *flags) {
101104
m_options.store(options, std::memory_order_relaxed);
102105
m_handler = handler_sp;
103106
m_channel.log_ptr.store(this, std::memory_order_relaxed);
104107
}
105108
}
106109

107-
void Log::Disable(Log::MaskType flags) {
110+
void Log::Disable(std::optional<Log::MaskType> flags) {
108111
llvm::sys::ScopedWriter lock(m_mutex);
109112

110-
MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
111-
if (!(mask & ~flags)) {
113+
if (!flags)
114+
flags = std::numeric_limits<MaskType>::max();
115+
116+
MaskType mask = m_mask.fetch_and(~(*flags), std::memory_order_relaxed);
117+
if (!(mask & ~(*flags))) {
112118
m_handler.reset();
113119
m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
114120
}
@@ -230,10 +236,11 @@ bool Log::EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
230236
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
231237
return false;
232238
}
233-
MaskType flags = categories.empty()
234-
? iter->second.m_channel.default_flags
235-
: GetFlags(error_stream, *iter, categories);
236-
iter->second.Enable(log_handler_sp, log_options, flags);
239+
240+
auto flags = categories.empty() ? std::optional<MaskType>{}
241+
: GetFlags(error_stream, *iter, categories);
242+
243+
iter->second.Enable(log_handler_sp, flags, log_options);
237244
return true;
238245
}
239246

@@ -245,9 +252,10 @@ bool Log::DisableLogChannel(llvm::StringRef channel,
245252
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
246253
return false;
247254
}
248-
MaskType flags = categories.empty()
249-
? std::numeric_limits<MaskType>::max()
250-
: GetFlags(error_stream, *iter, categories);
255+
256+
auto flags = categories.empty() ? std::optional<MaskType>{}
257+
: GetFlags(error_stream, *iter, categories);
258+
251259
iter->second.Disable(flags);
252260
return true;
253261
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
RUN: %lldb -o 'log list' -o 'log disable system' 2>&1 | FileCheck %s
2+
CHECK-NOT: Logging categories for 'system'
3+
CHECK: Invalid log channel 'system'

0 commit comments

Comments
 (0)