From 3b092bd9b6b3953d5c3052d57e4827dbd85941fd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 9 Mar 2017 10:37:45 +0000 Subject: [PATCH 1/2] util: Properly handle errors during log message formatting Instead of having an exception propagate into the program when an error happens while formatting a log message, just print a message to the log. Addresses #9423. --- src/util.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/util.h b/src/util.h index e27ce121c..c9d465954 100644 --- a/src/util.h +++ b/src/util.h @@ -73,14 +73,24 @@ bool LogAcceptCategory(const char* category); /** Send a string to the log output */ int LogPrintStr(const std::string &str); -#define LogPrint(category, ...) do { \ - if (LogAcceptCategory((category))) { \ - LogPrintStr(tfm::format(__VA_ARGS__)); \ - } \ -} while(0) +/** Get format string from VA_ARGS for error reporting */ +template std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; } #define LogPrintf(...) do { \ - LogPrintStr(tfm::format(__VA_ARGS__)); \ + std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \ + try { \ + _log_msg_ = tfm::format(__VA_ARGS__); \ + } catch (std::runtime_error &e) { \ + /* Original format string will have newline so don't add one here */ \ + _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \ + } \ + LogPrintStr(_log_msg_); \ +} while(0) + +#define LogPrint(category, ...) do { \ + if (LogAcceptCategory((category))) { \ + LogPrintf(__VA_ARGS__); \ + } \ } while(0) template From b651270cd6bfdd6d7c4acf04d1a00c03bf09f03a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 13 Mar 2017 06:51:15 +0100 Subject: [PATCH 2/2] util: Throw tinyformat::format_error on formatting error Throw tinyformat::format_error on formatting error instead of the `std::runtime_error`. --- src/tinyformat.h | 9 ++++++++- src/util.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/tinyformat.h b/src/tinyformat.h index 17f0360c4..5022d4680 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -123,7 +123,7 @@ namespace tinyformat {} namespace tfm = tinyformat; // Error handling; calls assert() by default. -#define TINYFORMAT_ERROR(reasonString) throw std::runtime_error(reasonString) +#define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString) // Define for C++11 variadic templates which make the code shorter & more // general. If you don't define this, C++11 support is autodetected below. @@ -164,6 +164,13 @@ namespace tfm = tinyformat; namespace tinyformat { +class format_error: public std::runtime_error +{ +public: + format_error(const std::string &what): std::runtime_error(what) { + } +}; + //------------------------------------------------------------------------------ namespace detail { diff --git a/src/util.h b/src/util.h index c9d465954..87eb16c91 100644 --- a/src/util.h +++ b/src/util.h @@ -80,7 +80,7 @@ template std::string FormatStringFromLogArgs(const char *fmt, std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \ try { \ _log_msg_ = tfm::format(__VA_ARGS__); \ - } catch (std::runtime_error &e) { \ + } catch (tinyformat::format_error &e) { \ /* Original format string will have newline so don't add one here */ \ _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \ } \