Remove lldb streams from the Log class completely

Summary:
previously we switched to llvm streams for log output, this completes
the switch for the error streams.

I also clean up the includes and remove the unused argument from
DisableAllLogChannels().

This required adding a bit of boiler plate to convert the output in the
command interpreter, but that should go away when we switch command
results to use llvm streams as well.

Reviewers: zturner, eugene

Subscribers: lldb-commits, emaste

Differential Revision: https://reviews.llvm.org/D30894

llvm-svn: 297812
This commit is contained in:
Pavel Labath 2017-03-15 09:06:58 +00:00
parent 6de25ec61a
commit 775588c0c3
14 changed files with 130 additions and 113 deletions

View File

@ -195,7 +195,7 @@ public:
bool EnableLog(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
llvm::StringRef log_file, uint32_t log_options,
Stream &error_stream);
llvm::raw_ostream &error_stream);
void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton);

View File

@ -13,9 +13,9 @@
// Project includes
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/Logging.h"
#include "lldb/lldb-private.h"
// Other libraries and framework includes
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/RWMutex.h"
@ -100,17 +100,17 @@ public:
EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
uint32_t log_options, llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
Stream &error_stream);
llvm::raw_ostream &error_stream);
static bool DisableLogChannel(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
Stream &error_stream);
llvm::raw_ostream &error_stream);
static bool ListChannelCategories(llvm::StringRef channel, Stream &stream);
static bool ListChannelCategories(llvm::StringRef channel, llvm::raw_ostream &stream);
static void DisableAllLogChannels(Stream *feedback_strm);
static void DisableAllLogChannels();
static void ListAllLogChannels(Stream *strm);
static void ListAllLogChannels(llvm::raw_ostream &stream);
//------------------------------------------------------------------
// Member functions
@ -131,7 +131,6 @@ public:
Format(file, function, llvm::formatv(format, std::forward<Args>(args)...));
}
// CLEANUP: Add llvm::raw_ostream &Stream() function.
void Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
void VAPrintf(const char *format, va_list args);
@ -183,12 +182,13 @@ private:
typedef llvm::StringMap<Log> ChannelMap;
static llvm::ManagedStatic<ChannelMap> g_channel_map;
static void ListCategories(Stream &stream,
static void ListCategories(llvm::raw_ostream &stream,
const ChannelMap::value_type &entry);
static uint32_t GetFlags(Stream &stream, const ChannelMap::value_type &entry,
static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry,
llvm::ArrayRef<const char *> categories);
DISALLOW_COPY_AND_ASSIGN(Log);
Log(const Log &) = delete;
void operator=(const Log &) = delete;
};
} // namespace lldb_private

View File

@ -10,10 +10,7 @@
#ifndef LLDB_UTILITY_LOGGING_H
#define LLDB_UTILITY_LOGGING_H
// Project includes
#include "lldb/lldb-private.h"
// Other libraries and framework includes
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
//----------------------------------------------------------------------
// Log Bits specific to logging in lldb
@ -56,6 +53,8 @@
namespace lldb_private {
class Log;
void LogIfAnyCategoriesSet(uint32_t mask, const char *format, ...);
Log *GetLogIfAllCategoriesSet(uint32_t mask);

View File

@ -1133,9 +1133,10 @@ bool SBDebugger::EnableLog(const char *channel, const char **categories) {
if (m_opaque_sp) {
uint32_t log_options =
LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
StreamString errors;
std::string error;
llvm::raw_string_ostream error_stream(error);
return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "",
log_options, errors);
log_options, error_stream);
} else
return false;
}

View File

@ -170,9 +170,14 @@ protected:
m_options.log_file.GetPath(log_file, sizeof(log_file));
else
log_file[0] = '\0';
std::string error;
llvm::raw_string_ostream error_stream(error);
bool success = m_interpreter.GetDebugger().EnableLog(
channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
result.GetErrorStream());
error_stream);
result.GetErrorStream() << error_stream.str();
if (success)
result.SetStatus(eReturnStatusSuccessFinishNoResult);
else
@ -229,12 +234,15 @@ protected:
const std::string channel = args[0].ref;
args.Shift(); // Shift off the channel
if (channel == "all") {
Log::DisableAllLogChannels(&result.GetErrorStream());
Log::DisableAllLogChannels();
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
std::string error;
llvm::raw_string_ostream error_stream(error);
if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
result.GetErrorStream()))
error_stream))
result.SetStatus(eReturnStatusSuccessFinishNoResult);
result.GetErrorStream() << error_stream.str();
}
return result.Succeeded();
}
@ -269,17 +277,20 @@ public:
protected:
bool DoExecute(Args &args, CommandReturnObject &result) override {
std::string output;
llvm::raw_string_ostream output_stream(output);
if (args.empty()) {
Log::ListAllLogChannels(&result.GetOutputStream());
Log::ListAllLogChannels(output_stream);
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
bool success = true;
for (const auto &entry : args.entries())
success = success && Log::ListChannelCategories(
entry.ref, result.GetOutputStream());
success =
success && Log::ListChannelCategories(entry.ref, output_stream);
if (success)
result.SetStatus(eReturnStatusSuccessFinishResult);
}
result.GetOutputStream() << output_stream.str();
return result.Succeeded();
}
};

View File

@ -1242,7 +1242,7 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
bool Debugger::EnableLog(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
llvm::StringRef log_file, uint32_t log_options,
Stream &error_stream) {
llvm::raw_ostream &error_stream) {
const bool should_close = true;
const bool unbuffered = true;
@ -1266,7 +1266,7 @@ bool Debugger::EnableLog(llvm::StringRef channel,
int FD;
if (std::error_code ec =
llvm::sys::fs::openFileForWrite(log_file, FD, flags)) {
error_stream.Format("Unable to open log file: {0}", ec.message());
error_stream << "Unable to open log file: " << ec.message();
return false;
}
log_stream_sp.reset(

View File

@ -93,9 +93,8 @@ static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd,
static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
const ProcessLaunchInfo &info) {
// First, make sure we disable all logging. If we are logging to stdout, our
// logs can be
// mistaken for inferior output.
Log::DisableAllLogChannels(nullptr);
// logs can be mistaken for inferior output.
Log::DisableAllLogChannels();
// Do not inherit setgid powers.
if (setgid(getgid()) != 0)

View File

@ -121,5 +121,5 @@ void SystemInitializerCommon::Terminate() {
#endif
HostInfo::Terminate();
Log::DisableAllLogChannels(nullptr);
Log::DisableAllLogChannels();
}

View File

@ -12,7 +12,6 @@
#include "llvm/Support/Threading.h"
using namespace lldb;
using namespace lldb_private;
static constexpr Log::Category g_categories[] = {

View File

@ -9,7 +9,6 @@
#include "LogChannelDWARF.h"
using namespace lldb;
using namespace lldb_private;
static constexpr Log::Category g_categories[] = {

View File

@ -9,10 +9,8 @@
// Project includes
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/VASPrintf.h"
#include "lldb/lldb-types.h"
// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
@ -32,20 +30,20 @@
#include <mutex>
#include <string>
using namespace lldb;
using namespace lldb_private;
llvm::ManagedStatic<Log::ChannelMap> Log::g_channel_map;
void Log::ListCategories(Stream &stream, const ChannelMap::value_type &entry) {
stream.Format("Logging categories for '{0}':\n", entry.first());
stream.Format(" all - all available logging categories\n");
stream.Format(" default - default set of logging categories\n");
void Log::ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry) {
stream << llvm::formatv("Logging categories for '{0}':\n", entry.first());
stream << " all - all available logging categories\n";
stream << " default - default set of logging categories\n";
for (const auto &category : entry.second.m_channel.categories)
stream.Format(" {0} - {1}\n", category.name, category.description);
stream << llvm::formatv(" {0} - {1}\n", category.name,
category.description);
}
uint32_t Log::GetFlags(Stream &stream, const ChannelMap::value_type &entry,
uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry,
llvm::ArrayRef<const char *> categories) {
bool list_categories = false;
uint32_t flags = 0;
@ -65,7 +63,8 @@ uint32_t Log::GetFlags(Stream &stream, const ChannelMap::value_type &entry,
flags |= cat->flag;
continue;
}
stream.Format("error: unrecognized log category '{0}'\n", category);
stream << llvm::formatv("error: unrecognized log category '{0}'\n",
category);
list_categories = true;
}
if (list_categories)
@ -194,10 +193,10 @@ void Log::Unregister(llvm::StringRef name) {
bool Log::EnableLogChannel(
const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
uint32_t log_options, llvm::StringRef channel,
llvm::ArrayRef<const char *> categories, Stream &error_stream) {
llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
auto iter = g_channel_map->find(channel);
if (iter == g_channel_map->end()) {
error_stream.Format("Invalid log channel '{0}'.\n", channel);
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
return false;
}
uint32_t flags = categories.empty()
@ -209,10 +208,10 @@ bool Log::EnableLogChannel(
bool Log::DisableLogChannel(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
Stream &error_stream) {
llvm::raw_ostream &error_stream) {
auto iter = g_channel_map->find(channel);
if (iter == g_channel_map->end()) {
error_stream.Format("Invalid log channel '{0}'.\n", channel);
error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
return false;
}
uint32_t flags = categories.empty()
@ -222,30 +221,32 @@ bool Log::DisableLogChannel(llvm::StringRef channel,
return true;
}
bool Log::ListChannelCategories(llvm::StringRef channel, Stream &stream) {
bool Log::ListChannelCategories(llvm::StringRef channel,
llvm::raw_ostream &stream) {
auto ch = g_channel_map->find(channel);
if (ch == g_channel_map->end()) {
stream.Format("Invalid log channel '{0}'.\n", channel);
stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
return false;
}
ListCategories(stream, *ch);
return true;
}
void Log::DisableAllLogChannels(Stream *feedback_strm) {
void Log::DisableAllLogChannels() {
for (auto &entry : *g_channel_map)
entry.second.Disable(UINT32_MAX);
}
void Log::ListAllLogChannels(Stream *strm) {
void Log::ListAllLogChannels(llvm::raw_ostream &stream) {
if (g_channel_map->empty()) {
strm->PutCString("No logging channels are currently registered.\n");
stream << "No logging channels are currently registered.\n";
return;
}
for (const auto &channel : *g_channel_map)
ListCategories(*strm, channel);
ListCategories(stream, channel);
}
bool Log::GetVerbose() const {
return m_options.load(std::memory_order_relaxed) & LLDB_LOG_OPTION_VERBOSE;
}

View File

@ -8,17 +8,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/Logging.h"
// C Includes
// C++ Includes
#include <atomic>
#include <cstring>
// Other libraries and framework includes
// Project includes
#include "lldb/Utility/Log.h"
using namespace lldb;
using namespace lldb_private;
static constexpr Log::Category g_categories[] = {

View File

@ -46,7 +46,8 @@ bool LLDBServerUtilities::SetupLogging(const std::string &log_file,
SmallVector<StringRef, 32> channel_array;
log_channels.split(channel_array, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
for (auto channel_with_categories : channel_array) {
StreamString error_stream;
std::string error;
llvm::raw_string_ostream error_stream(error);
Args channel_then_categories(channel_with_categories);
std::string channel(channel_then_categories.GetArgumentAtIndex(0));
channel_then_categories.Shift(); // Shift off the channel
@ -55,8 +56,8 @@ bool LLDBServerUtilities::SetupLogging(const std::string &log_file,
log_stream_sp, log_options, channel,
channel_then_categories.GetArgumentArrayRef(), error_stream);
if (!success) {
fprintf(stderr, "Unable to open log file '%s' for channel \"%s\"\n",
log_file.c_str(), channel_with_categories.str().c_str());
errs() << formatv("Unable to setup logging for channel \"{0}\": {1}",
channel, error_stream.str());
return false;
}
}

View File

@ -27,7 +27,7 @@ static constexpr uint32_t default_flags = FOO;
static Log::Channel test_channel(test_categories, default_flags);
struct LogChannelTest : public ::testing::Test {
void TearDown() override { Log::DisableAllLogChannels(nullptr); }
void TearDown() override { Log::DisableAllLogChannels(); }
static void SetUpTestCase() {
Log::Register("chan", test_channel);
@ -39,6 +39,31 @@ struct LogChannelTest : public ::testing::Test {
}
};
// Wrap enable, disable and list functions to make them easier to test.
static bool EnableChannel(std::shared_ptr<llvm::raw_ostream> stream_sp,
uint32_t log_options, llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
std::string &error) {
error.clear();
llvm::raw_string_ostream error_stream(error);
return Log::EnableLogChannel(stream_sp, log_options, channel, categories,
error_stream);
}
static bool DisableChannel(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
std::string &error) {
error.clear();
llvm::raw_string_ostream error_stream(error);
return Log::DisableLogChannel(channel, categories, error_stream);
}
static bool ListCategories(llvm::StringRef channel, std::string &result) {
result.clear();
llvm::raw_string_ostream result_stream(result);
return Log::ListChannelCategories(channel, result_stream);
}
TEST(LogTest, LLDB_LOG_nullptr) {
Log *log = nullptr;
LLDB_LOG(log, "{0}", 0); // Shouldn't crash
@ -56,12 +81,10 @@ TEST(LogTest, Unregister) {
llvm::llvm_shutdown_obj obj;
Log::Register("chan", test_channel);
EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO));
const char *cat1[] = {"foo"};
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat1, err));
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {"foo"}, llvm::nulls()));
EXPECT_NE(nullptr, test_channel.GetLogIfAny(FOO));
Log::Unregister("chan");
EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO));
@ -72,24 +95,20 @@ TEST_F(LogChannelTest, Enable) {
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_FALSE(Log::EnableLogChannel(stream_sp, 0, "chanchan", {}, err));
EXPECT_EQ("Invalid log channel 'chanchan'.\n", err.GetString());
err.Clear();
std::string error;
ASSERT_FALSE(EnableChannel(stream_sp, 0, "chanchan", {}, error));
EXPECT_EQ("Invalid log channel 'chanchan'.\n", error);
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {}, err));
EXPECT_EQ("", err.GetString()) << "err: " << err.GetString().str();
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, error));
EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO));
EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR));
const char *cat2[] = {"bar"};
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat2, err));
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"bar"}, error));
EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR));
const char *cat3[] = {"baz"};
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat3, err));
EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'"))
<< "err: " << err.GetString().str();
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"baz"}, error));
EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'"))
<< "error: " << error;
EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR));
}
@ -98,9 +117,9 @@ TEST_F(LogChannelTest, EnableOptions) {
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan",
{}, err));
std::string error;
EXPECT_TRUE(
EnableChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan", {}, error));
Log *log = test_channel.GetLogIfAll(FOO);
ASSERT_NE(nullptr, log);
@ -109,34 +128,30 @@ TEST_F(LogChannelTest, EnableOptions) {
TEST_F(LogChannelTest, Disable) {
EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO));
const char *cat12[] = {"foo", "bar"};
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat12, err));
std::string error;
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"foo", "bar"}, error));
EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR));
const char *cat2[] = {"bar"};
EXPECT_TRUE(Log::DisableLogChannel("chan", cat2, err));
EXPECT_TRUE(DisableChannel("chan", {"bar"}, error));
EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO));
EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR));
const char *cat3[] = {"baz"};
EXPECT_TRUE(Log::DisableLogChannel("chan", cat3, err));
EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'"))
<< "err: " << err.GetString().str();
EXPECT_TRUE(DisableChannel("chan", {"baz"}, error));
EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'"))
<< "error: " << error;
EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO));
EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR));
err.Clear();
EXPECT_TRUE(Log::DisableLogChannel("chan", {}, err));
EXPECT_TRUE(DisableChannel("chan", {}, error));
EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO | BAR));
}
TEST_F(LogChannelTest, List) {
StreamString str;
EXPECT_TRUE(Log::ListChannelCategories("chan", str));
std::string list;
EXPECT_TRUE(ListCategories("chan", list));
std::string expected =
R"(Logging categories for 'chan':
all - all available logging categories
@ -144,11 +159,10 @@ TEST_F(LogChannelTest, List) {
foo - log foo
bar - log bar
)";
EXPECT_EQ(expected, str.GetString().str());
str.Clear();
EXPECT_EQ(expected, list);
EXPECT_FALSE(Log::ListChannelCategories("chanchan", str));
EXPECT_EQ("Invalid log channel 'chanchan'.\n", str.GetString().str());
EXPECT_FALSE(ListCategories("chanchan", list));
EXPECT_EQ("Invalid log channel 'chanchan'.\n", list);
}
static std::string GetLogString(uint32_t log_options, const char *format,
@ -156,14 +170,16 @@ static std::string GetLogString(uint32_t log_options, const char *format,
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, log_options, "chan", {}, err));
std::string error;
llvm::raw_string_ostream error_stream(error);
EXPECT_TRUE(
Log::EnableLogChannel(stream_sp, log_options, "chan", {}, error_stream));
Log *log = test_channel.GetLogIfAll(FOO);
EXPECT_NE(nullptr, log);
LLDB_LOG(log, format, arg);
EXPECT_TRUE(Log::DisableLogChannel("chan", {}, err));
EXPECT_TRUE(Log::DisableLogChannel("chan", {}, error_stream));
return stream_sp->str();
}
@ -198,14 +214,14 @@ TEST_F(LogChannelTest, LogThread) {
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {}, err));
std::string err;
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, err));
Log *log = test_channel.GetLogIfAll(FOO);
// Start logging on one thread. Concurrently, try disabling the log channel.
std::thread log_thread([log] { LLDB_LOG(log, "Hello World"); });
EXPECT_TRUE(Log::DisableLogChannel("chan", {}, err));
EXPECT_TRUE(DisableChannel("chan", {}, err));
log_thread.join();
// The log thread either managed to write to the log in time, or it didn't. In
@ -221,18 +237,18 @@ TEST_F(LogChannelTest, LogVerboseThread) {
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {}, err));
std::string err;
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, err));
Log *log = test_channel.GetLogIfAll(FOO);
// Start logging on one thread. Concurrently, try enabling the log channel
// (with different log options).
std::thread log_thread([log] { LLDB_LOGV(log, "Hello World"); });
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan",
EXPECT_TRUE(EnableChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan",
{}, err));
log_thread.join();
EXPECT_TRUE(Log::DisableLogChannel("chan", {}, err));
EXPECT_TRUE(DisableChannel("chan", {}, err));
// The log thread either managed to write to the log, or it didn't. In either
// case, we should not trip any undefined behavior (run the test under TSAN to
@ -247,15 +263,15 @@ TEST_F(LogChannelTest, LogGetLogThread) {
std::string message;
std::shared_ptr<llvm::raw_string_ostream> stream_sp(
new llvm::raw_string_ostream(message));
StreamString err;
EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {}, err));
std::string err;
EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, err));
Log *log = test_channel.GetLogIfAll(FOO);
// Try fetching the log on one thread. Concurrently, try disabling the log
// channel.
uint32_t mask;
std::thread log_thread([log, &mask] { mask = log->GetMask().Get(); });
EXPECT_TRUE(Log::DisableLogChannel("chan", {}, err));
EXPECT_TRUE(DisableChannel("chan", {}, err));
log_thread.join();
// The mask should be either zero of "FOO". In either case, we should not trip