message: [Log] Handle errors during log message formatting
diff: @@ -71,6 +71,9 @@ int LogPrintStr(const std::string& str);
  #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
  +/** Get format string from VA_ARGS for error reporting */
  +template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; }
  +
  /**
  * When we switch to C++11, this can be switched to variadic templates instead
  * of this macro-based construction (see tinyformat.h).
  @@ -81,13 +84,25 @@ int LogPrintStr(const std::string& str);
  static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \
  { \
  if (!LogAcceptCategory(category)) return 0; \
  - return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \
  + std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
  + try { \
  + _log_msg_ = tfm::format(format, TINYFORMAT_PASSARGS(n)); \
  + } catch (std::runtime_error &e) { \
  + _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(format, TINYFORMAT_PASSARGS(n));\
  + } \
  + return LogPrintStr(_log_msg_); \
  } \
  /** Log error and return false */ \
  template <TINYFORMAT_ARGTYPES(n)> \
  static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \
  { \
  - LogPrintStr(std::string("ERROR: ") + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \
  + std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
  + try { \
  + _log_msg_ = tfm::format(format, TINYFORMAT_PASSARGS(n)); \
  + } catch (std::runtime_error &e) { \
  + _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(format, TINYFORMAT_PASSARGS(n));\
  + } \
  + LogPrintStr(std::string("ERROR: ") + _log_msg_ + "\n"); \
  return false; \
  }
  