summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-05-23 02:51:32 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-06-15 12:46:39 +0300
commit01e387acb0cc345fc9992498898efd167bf07b71 (patch)
tree5a2d7bd262495e47471fdd1d663e63789b4f4e3f
parent2f6b951b7561e6e725796b1d64a481ae306f3664 (diff)
libcamera: log: Destroy LogCategory instances in a controlled way
The LogCategory instances are constructed on first use as static variables in accessor functions, following the Meyers singleton pattern. As a result, their destruction order is not guaranteed. This can cause issues as the global Logger object, constructed in a similar fashion, is accessed from the LogCategory destructor and may be destroyed first. To fix this, keep the same singleton pattern, but allocate the LogCategory instances dynamically. As they get registered with the global Logger instance, we can destroy them in the Logger destructor. This only avoids destruction order issues between LogCategory and Logger, and doesn't address yet the fact that LOG() calls from destructors of global objects may access an already destroyed Logger. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Hirokazu Honda <hiroh@chormium.org> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r--include/libcamera/internal/log.h6
-rw-r--r--src/libcamera/log.cpp32
2 files changed, 14 insertions, 24 deletions
diff --git a/include/libcamera/internal/log.h b/include/libcamera/internal/log.h
index b66bf55b..b8efb161 100644
--- a/include/libcamera/internal/log.h
+++ b/include/libcamera/internal/log.h
@@ -29,7 +29,6 @@ class LogCategory
{
public:
explicit LogCategory(const char *name);
- ~LogCategory();
const char *name() const { return name_; }
LogSeverity severity() const { return severity_; }
@@ -48,8 +47,9 @@ extern const LogCategory &_LOG_CATEGORY(name)();
#define LOG_DEFINE_CATEGORY(name) \
const LogCategory &_LOG_CATEGORY(name)() \
{ \
- static LogCategory category(#name); \
- return category; \
+ /* The instance will be deleted by the Logger destructor. */ \
+ static LogCategory *category = new LogCategory(#name); \
+ return *category; \
}
class LogMessage
diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp
index dd991647..74829a56 100644
--- a/src/libcamera/log.cpp
+++ b/src/libcamera/log.cpp
@@ -248,6 +248,8 @@ void LogOutput::writeStream(const std::string &str)
class Logger
{
public:
+ ~Logger();
+
static Logger *instance();
void write(const LogMessage &msg);
@@ -267,7 +269,6 @@ private:
friend LogCategory;
void registerCategory(LogCategory *category);
- void unregisterCategory(LogCategory *category);
std::unordered_set<LogCategory *> categories_;
std::list<std::pair<std::string, LogSeverity>> levels_;
@@ -369,6 +370,12 @@ void logSetLevel(const char *category, const char *level)
Logger::instance()->logSetLevel(category, level);
}
+Logger::~Logger()
+{
+ for (LogCategory *category : categories_)
+ delete category;
+}
+
/**
* \brief Retrieve the logger instance
*
@@ -666,18 +673,6 @@ void Logger::registerCategory(LogCategory *category)
}
/**
- * \brief Unregister a log category from the logger
- * \param[in] category The log category
- *
- * If the \a category hasn't been registered with the logger this function
- * performs no operation.
- */
-void Logger::unregisterCategory(LogCategory *category)
-{
- categories_.erase(category);
-}
-
-/**
* \enum LogSeverity
* Log message severity
* \var LogDebug
@@ -711,11 +706,6 @@ LogCategory::LogCategory(const char *name)
Logger::instance()->registerCategory(this);
}
-LogCategory::~LogCategory()
-{
- Logger::instance()->unregisterCategory(this);
-}
-
/**
* \fn LogCategory::name()
* \brief Retrieve the log category name
@@ -746,12 +736,12 @@ void LogCategory::setSeverity(LogSeverity severity)
* The default log category is named "default" and is used by the LOG() macro
* when no log category is specified.
*
- * \return A pointer to the default log category
+ * \return A reference to the default log category
*/
const LogCategory &LogCategory::defaultCategory()
{
- static const LogCategory category("default");
- return category;
+ static const LogCategory *category = new LogCategory("default");
+ return *category;
}
/**