diff options
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | src/libcamera/log.cpp | 93 |
2 files changed, 79 insertions, 18 deletions
diff --git a/meson.build b/meson.build index 0a222ba9..63448858 100644 --- a/meson.build +++ b/meson.build @@ -26,6 +26,10 @@ libcamera_version = libcamera_git_version.split('+')[0] cc = meson.get_compiler('c') config_h = configuration_data() +if cc.has_header_symbol('execinfo.h', 'backtrace') + config_h.set('HAVE_BACKTRACE', 1) +endif + if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE') config_h.set('HAVE_SECURE_GETENV', 1) endif diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp index 50f345b9..f4eb8c11 100644 --- a/src/libcamera/log.cpp +++ b/src/libcamera/log.cpp @@ -7,6 +7,9 @@ #include "log.h" +#if HAVE_BACKTRACE +#include <execinfo.h> +#endif #include <fstream> #include <iostream> #include <list> @@ -108,10 +111,11 @@ public: bool isValid() const; void write(const LogMessage &msg); + void write(const std::string &msg); private: - void writeSyslog(const LogMessage &msg); - void writeStream(const LogMessage &msg); + void writeSyslog(LogSeverity severity, const std::string &msg); + void writeStream(const std::string &msg); std::ostream *stream_; LoggingTarget target_; @@ -181,33 +185,54 @@ bool LogOutput::isValid() const */ void LogOutput::write(const LogMessage &msg) { + std::string str; + + switch (target_) { + case LoggingTargetSyslog: + str = std::string(log_severity_name(msg.severity())) + " " + + msg.category().name() + " " + msg.fileInfo() + " " + + msg.msg(); + writeSyslog(msg.severity(), str); + break; + case LoggingTargetStream: + case LoggingTargetFile: + str = "[" + utils::time_point_to_string(msg.timestamp()) + "]" + + log_severity_name(msg.severity()) + " " + + msg.category().name() + " " + msg.fileInfo() + " " + + msg.msg(); + writeStream(str); + break; + default: + break; + } +} + +/** + * \brief Write string to log output + * \param[in] str String to write + */ +void LogOutput::write(const std::string &str) +{ switch (target_) { case LoggingTargetSyslog: - writeSyslog(msg); + writeSyslog(LogDebug, str); break; case LoggingTargetStream: case LoggingTargetFile: - writeStream(msg); + writeStream(str); break; default: break; } } -void LogOutput::writeSyslog(const LogMessage &msg) +void LogOutput::writeSyslog(LogSeverity severity, const std::string &str) { - std::string str = std::string(log_severity_name(msg.severity())) + " " + - msg.category().name() + " " + msg.fileInfo() + " " + - msg.msg(); - syslog(log_severity_to_syslog(msg.severity()), "%s", str.c_str()); + syslog(log_severity_to_syslog(severity), "%s", str.c_str()); } -void LogOutput::writeStream(const LogMessage &msg) +void LogOutput::writeStream(const std::string &str) { - std::string str = "[" + utils::time_point_to_string(msg.timestamp()) + - "]" + log_severity_name(msg.severity()) + " " + - msg.category().name() + " " + msg.fileInfo() + " " + - msg.msg(); stream_->write(str.c_str(), str.size()); stream_->flush(); } @@ -223,6 +248,7 @@ public: static Logger *instance(); void write(const LogMessage &msg); + void backtrace(); int logSetFile(const char *path); int logSetStream(std::ostream *stream); @@ -240,9 +266,6 @@ private: void registerCategory(LogCategory *category); void unregisterCategory(LogCategory *category); - void writeSyslog(const LogMessage &msg); - void writeStream(const LogMessage &msg); - std::unordered_set<LogCategory *> categories_; std::list<std::pair<std::string, LogSeverity>> levels_; @@ -371,6 +394,38 @@ void Logger::write(const LogMessage &msg) } /** + * \brief Write a backtrace to the log + */ +void Logger::backtrace() +{ +#if HAVE_BACKTRACE + std::shared_ptr<LogOutput> output = std::atomic_load(&output_); + if (!output) + return; + + void *buffer[32]; + int num_entries = ::backtrace(buffer, ARRAY_SIZE(buffer)); + char **strings = backtrace_symbols(buffer, num_entries); + if (!strings) + return; + + std::ostringstream msg; + msg << "Backtrace:" << std::endl; + + /* + * Skip the first two entries that correspond to this method and + * ~LogMessage(). + */ + for (int i = 2; i < num_entries; ++i) + msg << strings[i] << std::endl; + + output->write(msg.str()); + + free(strings); +#endif +} + +/** * \brief Set the log file * \param[in] path Full path to the log file * @@ -783,8 +838,10 @@ LogMessage::~LogMessage() if (severity_ >= category_.severity()) Logger::instance()->write(*this); - if (severity_ == LogSeverity::LogFatal) + if (severity_ == LogSeverity::LogFatal) { + Logger::instance()->backtrace(); std::abort(); + } } /** |