SetLogger should delete previously set custom logger. (#853)

As specified in the doc comment for SetLogger, "the logger becomes the
property of the logging module and should not be deleted by the caller".

Not only should the LogDestination delete a custom logger in its
destructor, but it should also delete a previous logger when another
logger is passed to SetLogger().

Co-authored-by: Sergiu Deitsch <sergiud@users.noreply.github.com>
This commit is contained in:
Andrei Polushin 2022-08-13 17:20:33 +07:00 committed by GitHub
parent 1fb4cc1958
commit 6d5b384507
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 10 deletions

View File

@ -594,6 +594,10 @@ class LogDestination {
static LogDestination* log_destination(LogSeverity severity); static LogDestination* log_destination(LogSeverity severity);
base::Logger* GetLoggerImpl() const { return logger_; }
void SetLoggerImpl(base::Logger* logger);
void ResetLoggerImpl() { SetLoggerImpl(&fileobject_); }
LogFileObject fileobject_; LogFileObject fileobject_;
base::Logger* logger_; // Either &fileobject_, or wrapper around it base::Logger* logger_; // Either &fileobject_, or wrapper around it
@ -643,10 +647,20 @@ LogDestination::LogDestination(LogSeverity severity,
} }
LogDestination::~LogDestination() { LogDestination::~LogDestination() {
ResetLoggerImpl();
}
void LogDestination::SetLoggerImpl(base::Logger* logger) {
if (logger_ == logger) {
// Prevent releasing currently held sink on reset
return;
}
if (logger_ && logger_ != &fileobject_) { if (logger_ && logger_ != &fileobject_) {
// Delete user-specified logger set via SetLogger(). // Delete user-specified logger set via SetLogger().
delete logger_; delete logger_;
} }
logger_ = logger;
} }
inline void LogDestination::FlushLogFilesUnsafe(int min_severity) { inline void LogDestination::FlushLogFilesUnsafe(int min_severity) {
@ -2021,12 +2035,12 @@ void LogMessage::SendToSyslogAndLog() {
base::Logger* base::GetLogger(LogSeverity severity) { base::Logger* base::GetLogger(LogSeverity severity) {
MutexLock l(&log_mutex); MutexLock l(&log_mutex);
return LogDestination::log_destination(severity)->logger_; return LogDestination::log_destination(severity)->GetLoggerImpl();
} }
void base::SetLogger(LogSeverity severity, base::Logger* logger) { void base::SetLogger(LogSeverity severity, base::Logger* logger) {
MutexLock l(&log_mutex); MutexLock l(&log_mutex);
LogDestination::log_destination(severity)->logger_ = logger; LogDestination::log_destination(severity)->SetLoggerImpl(logger);
} }
// L < log_mutex. Acquires and releases mutex_. // L < log_mutex. Acquires and releases mutex_.

View File

@ -842,6 +842,11 @@ static void TestExtension() {
struct MyLogger : public base::Logger { struct MyLogger : public base::Logger {
string data; string data;
explicit MyLogger(bool* set_on_destruction)
: set_on_destruction_(set_on_destruction) {}
~MyLogger() { *set_on_destruction_ = true; }
virtual void Write(bool /* should_flush */, virtual void Write(bool /* should_flush */,
time_t /* timestamp */, time_t /* timestamp */,
const char* message, const char* message,
@ -852,19 +857,25 @@ struct MyLogger : public base::Logger {
virtual void Flush() { } virtual void Flush() { }
virtual uint32 LogSize() { return data.length(); } virtual uint32 LogSize() { return data.length(); }
private:
bool* set_on_destruction_;
}; };
static void TestWrapper() { static void TestWrapper() {
fprintf(stderr, "==== Test log wrapper\n"); fprintf(stderr, "==== Test log wrapper\n");
MyLogger my_logger; bool custom_logger_deleted = false;
MyLogger* my_logger = new MyLogger(&custom_logger_deleted);
base::Logger* old_logger = base::GetLogger(GLOG_INFO); base::Logger* old_logger = base::GetLogger(GLOG_INFO);
base::SetLogger(GLOG_INFO, &my_logger); base::SetLogger(GLOG_INFO, my_logger);
LOG(INFO) << "Send to wrapped logger"; LOG(INFO) << "Send to wrapped logger";
CHECK(strstr(my_logger->data.c_str(), "Send to wrapped logger") != NULL);
FlushLogFiles(GLOG_INFO); FlushLogFiles(GLOG_INFO);
base::SetLogger(GLOG_INFO, old_logger);
CHECK(strstr(my_logger.data.c_str(), "Send to wrapped logger") != NULL); EXPECT_FALSE(custom_logger_deleted);
base::SetLogger(GLOG_INFO, old_logger);
EXPECT_TRUE(custom_logger_deleted);
} }
static void TestErrno() { static void TestErrno() {

View File

@ -853,6 +853,11 @@ static void TestExtension() {
struct MyLogger : public base::Logger { struct MyLogger : public base::Logger {
string data; string data;
explicit MyLogger(bool* set_on_destruction)
: set_on_destruction_(set_on_destruction) {}
~MyLogger() { *set_on_destruction_ = true; }
virtual void Write(bool /* should_flush */, virtual void Write(bool /* should_flush */,
time_t /* timestamp */, time_t /* timestamp */,
const char* message, const char* message,
@ -863,19 +868,25 @@ struct MyLogger : public base::Logger {
virtual void Flush() { } virtual void Flush() { }
virtual uint32 LogSize() { return data.length(); } virtual uint32 LogSize() { return data.length(); }
private:
bool* set_on_destruction_;
}; };
static void TestWrapper() { static void TestWrapper() {
fprintf(stderr, "==== Test log wrapper\n"); fprintf(stderr, "==== Test log wrapper\n");
MyLogger my_logger; bool custom_logger_deleted = false;
MyLogger* my_logger = new MyLogger(&custom_logger_deleted);
base::Logger* old_logger = base::GetLogger(GLOG_INFO); base::Logger* old_logger = base::GetLogger(GLOG_INFO);
base::SetLogger(GLOG_INFO, &my_logger); base::SetLogger(GLOG_INFO, my_logger);
LOG(INFO) << "Send to wrapped logger"; LOG(INFO) << "Send to wrapped logger";
CHECK(strstr(my_logger->data.c_str(), "Send to wrapped logger") != NULL);
FlushLogFiles(GLOG_INFO); FlushLogFiles(GLOG_INFO);
base::SetLogger(GLOG_INFO, old_logger);
CHECK(strstr(my_logger.data.c_str(), "Send to wrapped logger") != NULL); EXPECT_FALSE(custom_logger_deleted);
base::SetLogger(GLOG_INFO, old_logger);
EXPECT_TRUE(custom_logger_deleted);
} }
static void TestErrno() { static void TestErrno() {