Skip to content

Commit 6ff49af

Browse files
committed
[lldb] Introduce the concept of a log handler (NFC)
This patch introduces the concept of a log handlers. Log handlers allow customizing the way log output is emitted. The StreamCallback class tried to do something conceptually similar. The benefit of the log handler interface is that you don't need to conform to llvm's raw_ostream interface. Differential revision: https://reviews.llvm.org/D127922
1 parent 4c77d02 commit 6ff49af

File tree

11 files changed

+194
-176
lines changed

11 files changed

+194
-176
lines changed

Diff for: lldb/include/lldb/Core/Debugger.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ class ThreadPool;
5454

5555
namespace lldb_private {
5656
class Address;
57+
class CallbackLogHandler;
5758
class CommandInterpreter;
59+
class LogHandler;
5860
class Process;
5961
class Stream;
6062
class SymbolContext;
@@ -553,8 +555,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
553555

554556
llvm::Optional<uint64_t> m_current_event_id;
555557

556-
llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams;
557-
std::shared_ptr<llvm::raw_ostream> m_log_callback_stream_sp;
558+
llvm::StringMap<std::weak_ptr<LogHandler>> m_stream_handlers;
559+
std::shared_ptr<CallbackLogHandler> m_callback_handler_sp;
558560
ConstString m_instance_name;
559561
static LoadPluginCallbackType g_load_plugin_callback;
560562
typedef std::vector<llvm::sys::DynamicLibrary> LoadedPluginsList;

Diff for: lldb/include/lldb/Utility/Log.h

+43-6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <cstdarg>
2626
#include <cstdint>
2727
#include <memory>
28+
#include <mutex>
2829
#include <string>
2930
#include <type_traits>
3031

@@ -45,6 +46,42 @@ class raw_ostream;
4546
// Logging Functions
4647
namespace lldb_private {
4748

49+
class LogHandler {
50+
public:
51+
virtual ~LogHandler() = default;
52+
virtual void Emit(llvm::StringRef message) = 0;
53+
void EmitThreadSafe(llvm::StringRef message);
54+
55+
private:
56+
std::mutex m_mutex;
57+
};
58+
59+
class StreamLogHandler : public LogHandler {
60+
public:
61+
StreamLogHandler(int fd, bool should_close, bool unbuffered);
62+
63+
void Emit(llvm::StringRef message) override;
64+
65+
static std::shared_ptr<StreamLogHandler> Create(int fd, bool unbuffered);
66+
67+
private:
68+
llvm::raw_fd_ostream m_stream;
69+
};
70+
71+
class CallbackLogHandler : public LogHandler {
72+
public:
73+
CallbackLogHandler(lldb::LogOutputCallback callback, void *baton);
74+
75+
void Emit(llvm::StringRef message) override;
76+
77+
static std::shared_ptr<CallbackLogHandler>
78+
Create(lldb::LogOutputCallback callback, void *baton);
79+
80+
private:
81+
lldb::LogOutputCallback m_callback;
82+
void *m_baton;
83+
};
84+
4885
class Log final {
4986
public:
5087
/// The underlying type of all log channel enums. Declare them as:
@@ -111,7 +148,7 @@ class Log final {
111148
static void Unregister(llvm::StringRef name);
112149

113150
static bool
114-
EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
151+
EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
115152
uint32_t log_options, llvm::StringRef channel,
116153
llvm::ArrayRef<const char *> categories,
117154
llvm::raw_ostream &error_stream);
@@ -188,7 +225,7 @@ class Log final {
188225
// Their modification however, is still protected by this mutex.
189226
llvm::sys::RWMutex m_mutex;
190227

191-
std::shared_ptr<llvm::raw_ostream> m_stream_sp;
228+
std::shared_ptr<LogHandler> m_handler;
192229
std::atomic<uint32_t> m_options{0};
193230
std::atomic<MaskType> m_mask{0};
194231

@@ -199,13 +236,13 @@ class Log final {
199236
void Format(llvm::StringRef file, llvm::StringRef function,
200237
const llvm::formatv_object_base &payload);
201238

202-
std::shared_ptr<llvm::raw_ostream> GetStream() {
239+
std::shared_ptr<LogHandler> GetHandler() {
203240
llvm::sys::ScopedReader lock(m_mutex);
204-
return m_stream_sp;
241+
return m_handler;
205242
}
206243

207-
void Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
208-
uint32_t options, uint32_t flags);
244+
void Enable(const std::shared_ptr<LogHandler> &handler_sp, uint32_t options,
245+
uint32_t flags);
209246

210247
void Disable(uint32_t flags);
211248

Diff for: lldb/include/lldb/Utility/StreamCallback.h

-35
This file was deleted.

Diff for: lldb/source/Core/Debugger.cpp

+16-20
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
#include "lldb/Utility/ReproducerProvider.h"
5252
#include "lldb/Utility/State.h"
5353
#include "lldb/Utility/Stream.h"
54-
#include "lldb/Utility/StreamCallback.h"
5554
#include "lldb/Utility/StreamString.h"
5655

5756
#if defined(_WIN32)
@@ -758,8 +757,7 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
758757
m_forward_listener_sp(), m_clear_once() {
759758
m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
760759
if (log_callback)
761-
m_log_callback_stream_sp =
762-
std::make_shared<StreamCallback>(log_callback, baton);
760+
m_callback_handler_sp = CallbackLogHandler::Create(log_callback, baton);
763761
m_command_interpreter_up->Initialize();
764762
// Always add our default platform to the platform list
765763
PlatformSP default_platform_sp(Platform::GetHostPlatform());
@@ -1292,8 +1290,7 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
12921290
// For simplicity's sake, I am not going to deal with how to close down any
12931291
// open logging streams, I just redirect everything from here on out to the
12941292
// callback.
1295-
m_log_callback_stream_sp =
1296-
std::make_shared<StreamCallback>(log_callback, baton);
1293+
m_callback_handler_sp = CallbackLogHandler::Create(log_callback, baton);
12971294
}
12981295

12991296
static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
@@ -1412,22 +1409,21 @@ bool Debugger::EnableLog(llvm::StringRef channel,
14121409
llvm::StringRef log_file, uint32_t log_options,
14131410
llvm::raw_ostream &error_stream) {
14141411
const bool should_close = true;
1415-
const bool unbuffered = true;
14161412

1417-
std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1418-
if (m_log_callback_stream_sp) {
1419-
log_stream_sp = m_log_callback_stream_sp;
1413+
std::shared_ptr<LogHandler> log_handler_sp;
1414+
if (m_callback_handler_sp) {
1415+
log_handler_sp = m_callback_handler_sp;
14201416
// For now when using the callback mode you always get thread & timestamp.
14211417
log_options |=
14221418
LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
14231419
} else if (log_file.empty()) {
1424-
log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
1425-
GetOutputFile().GetDescriptor(), !should_close, unbuffered);
1420+
log_handler_sp = StreamLogHandler::Create(GetOutputFile().GetDescriptor(),
1421+
!should_close);
14261422
} else {
1427-
auto pos = m_log_streams.find(log_file);
1428-
if (pos != m_log_streams.end())
1429-
log_stream_sp = pos->second.lock();
1430-
if (!log_stream_sp) {
1423+
auto pos = m_stream_handlers.find(log_file);
1424+
if (pos != m_stream_handlers.end())
1425+
log_handler_sp = pos->second.lock();
1426+
if (!log_handler_sp) {
14311427
File::OpenOptions flags =
14321428
File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
14331429
if (log_options & LLDB_LOG_OPTION_APPEND)
@@ -1442,18 +1438,18 @@ bool Debugger::EnableLog(llvm::StringRef channel,
14421438
return false;
14431439
}
14441440

1445-
log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
1446-
(*file)->GetDescriptor(), should_close, unbuffered);
1447-
m_log_streams[log_file] = log_stream_sp;
1441+
log_handler_sp =
1442+
StreamLogHandler::Create((*file)->GetDescriptor(), should_close);
1443+
m_stream_handlers[log_file] = log_handler_sp;
14481444
}
14491445
}
1450-
assert(log_stream_sp);
1446+
assert(log_handler_sp);
14511447

14521448
if (log_options == 0)
14531449
log_options =
14541450
LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
14551451

1456-
return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1452+
return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
14571453
error_stream);
14581454
}
14591455

Diff for: lldb/source/Utility/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ add_lldb_library(lldbUtility
5656
State.cpp
5757
Status.cpp
5858
Stream.cpp
59-
StreamCallback.cpp
6059
StreamString.cpp
6160
StringExtractor.cpp
6261
StringExtractorGDBRemote.cpp

Diff for: lldb/source/Utility/Log.cpp

+46-19
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &
8484
return flags;
8585
}
8686

87-
void Log::Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
87+
void Log::Enable(const std::shared_ptr<LogHandler> &handler_sp,
8888
uint32_t options, uint32_t flags) {
8989
llvm::sys::ScopedWriter lock(m_mutex);
9090

9191
MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed);
9292
if (mask | flags) {
9393
m_options.store(options, std::memory_order_relaxed);
94-
m_stream_sp = stream_sp;
94+
m_handler = handler_sp;
9595
m_channel.log_ptr.store(this, std::memory_order_relaxed);
9696
}
9797
}
@@ -101,7 +101,7 @@ void Log::Disable(uint32_t flags) {
101101

102102
MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
103103
if (!(mask & ~flags)) {
104-
m_stream_sp.reset();
104+
m_handler.reset();
105105
m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
106106
}
107107
}
@@ -191,10 +191,10 @@ void Log::Unregister(llvm::StringRef name) {
191191
g_channel_map->erase(iter);
192192
}
193193

194-
bool Log::EnableLogChannel(
195-
const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
196-
uint32_t log_options, llvm::StringRef channel,
197-
llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
194+
bool Log::EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
195+
uint32_t log_options, llvm::StringRef channel,
196+
llvm::ArrayRef<const char *> categories,
197+
llvm::raw_ostream &error_stream) {
198198
auto iter = g_channel_map->find(channel);
199199
if (iter == g_channel_map->end()) {
200200
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
@@ -203,7 +203,7 @@ bool Log::EnableLogChannel(
203203
uint32_t flags = categories.empty()
204204
? iter->second.m_channel.default_flags
205205
: GetFlags(error_stream, *iter, categories);
206-
iter->second.Enable(log_stream_sp, log_options, flags);
206+
iter->second.Enable(log_handler_sp, log_options, flags);
207207
return true;
208208
}
209209

@@ -314,20 +314,15 @@ void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
314314
void Log::WriteMessage(const std::string &message) {
315315
// Make a copy of our stream shared pointer in case someone disables our log
316316
// while we are logging and releases the stream
317-
auto stream_sp = GetStream();
318-
if (!stream_sp)
317+
auto handler_sp = GetHandler();
318+
if (!handler_sp)
319319
return;
320320

321321
Flags options = GetOptions();
322-
if (options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
323-
static std::recursive_mutex g_LogThreadedMutex;
324-
std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
325-
*stream_sp << message;
326-
stream_sp->flush();
327-
} else {
328-
*stream_sp << message;
329-
stream_sp->flush();
330-
}
322+
if (options.Test(LLDB_LOG_OPTION_THREADSAFE))
323+
handler_sp->EmitThreadSafe(message);
324+
else
325+
handler_sp->Emit(message);
331326
}
332327

333328
void Log::Format(llvm::StringRef file, llvm::StringRef function,
@@ -338,3 +333,35 @@ void Log::Format(llvm::StringRef file, llvm::StringRef function,
338333
message << payload << "\n";
339334
WriteMessage(message.str());
340335
}
336+
337+
void LogHandler::EmitThreadSafe(llvm::StringRef message) {
338+
std::lock_guard<std::mutex> guard(m_mutex);
339+
Emit(message);
340+
}
341+
342+
StreamLogHandler::StreamLogHandler(int fd, bool should_close, bool unbuffered)
343+
: m_stream(fd, should_close, unbuffered) {}
344+
345+
void StreamLogHandler::Emit(llvm::StringRef message) {
346+
m_stream << message;
347+
m_stream.flush();
348+
}
349+
350+
std::shared_ptr<StreamLogHandler> StreamLogHandler::Create(int fd,
351+
bool should_close) {
352+
constexpr const bool unbuffered = true;
353+
return std::make_shared<StreamLogHandler>(fd, should_close, unbuffered);
354+
}
355+
356+
CallbackLogHandler::CallbackLogHandler(lldb::LogOutputCallback callback,
357+
void *baton)
358+
: m_callback(callback), m_baton(baton) {}
359+
360+
void CallbackLogHandler::Emit(llvm::StringRef message) {
361+
m_callback(message.data(), m_baton);
362+
}
363+
364+
std::shared_ptr<CallbackLogHandler>
365+
CallbackLogHandler::Create(lldb::LogOutputCallback callback, void *baton) {
366+
return std::make_shared<CallbackLogHandler>(callback, baton);
367+
}

Diff for: lldb/source/Utility/StreamCallback.cpp

-22
This file was deleted.

0 commit comments

Comments
 (0)