kaldi-error.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // base/kaldi-error.h
  2. // Copyright 2019 LAIX (Yi Sun)
  3. // Copyright 2019 SmartAction LLC (kkm)
  4. // Copyright 2016 Brno University of Technology (author: Karel Vesely)
  5. // Copyright 2009-2011 Microsoft Corporation; Ondrej Glembek; Lukas Burget;
  6. // Saarland University
  7. // See ../../COPYING for clarification regarding multiple authors
  8. //
  9. // Licensed under the Apache License, Version 2.0 (the "License");
  10. // you may not use this file except in compliance with the License.
  11. // You may obtain a copy of the License at
  12. //
  13. // http://www.apache.org/licenses/LICENSE-2.0
  14. //
  15. // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  17. // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  18. // MERCHANTABLITY OR NON-INFRINGEMENT.
  19. // See the Apache 2 License for the specific language governing permissions and
  20. // limitations under the License.
  21. #ifndef KALDI_BASE_KALDI_ERROR_H_
  22. #define KALDI_BASE_KALDI_ERROR_H_ 1
  23. #include <cstdio>
  24. #include <cstring>
  25. #include <sstream>
  26. #include <stdexcept>
  27. #include <string>
  28. #include <vector>
  29. #include "base/kaldi-types.h"
  30. #include "base/kaldi-utils.h"
  31. /* Important that this file does not depend on any other kaldi headers. */
  32. #ifdef _MSC_VER
  33. #define __func__ __FUNCTION__
  34. #endif
  35. namespace kaldi {
  36. /// \addtogroup error_group
  37. /// @{
  38. /***** PROGRAM NAME AND VERBOSITY LEVEL *****/
  39. /// Called by ParseOptions to set base name (no directory) of the executing
  40. /// program. The name is printed in logging code along with every message,
  41. /// because in our scripts, we often mix together the stderr of many programs.
  42. /// This function is very thread-unsafe.
  43. void SetProgramName(const char *basename);
  44. /// This is set by util/parse-options.{h,cc} if you set --verbose=? option.
  45. /// Do not use directly, prefer {Get,Set}VerboseLevel().
  46. extern int32 g_kaldi_verbose_level;
  47. /// Get verbosity level, usually set via command line '--verbose=' switch.
  48. inline int32 GetVerboseLevel() { return g_kaldi_verbose_level; }
  49. /// This should be rarely used, except by programs using Kaldi as library;
  50. /// command-line programs set the verbose level automatically from ParseOptions.
  51. inline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }
  52. /***** KALDI LOGGING *****/
  53. /// Log message severity and source location info.
  54. struct LogMessageEnvelope {
  55. /// Message severity. In addition to these levels, positive values (1 to 6)
  56. /// specify verbose logging level. Verbose messages are produced only when
  57. /// SetVerboseLevel() has been called to set logging level to at least the
  58. /// corresponding value.
  59. enum Severity {
  60. kAssertFailed = -3, //!< Assertion failure. abort() will be called.
  61. kError = -2, //!< Fatal error. KaldiFatalError will be thrown.
  62. kWarning = -1, //!< Indicates a recoverable but abnormal condition.
  63. kInfo = 0, //!< Informational message.
  64. };
  65. int severity; //!< A Severity value, or positive verbosity level.
  66. const char *func; //!< Name of the function invoking the logging.
  67. const char *file; //!< Source file name with up to 1 leading directory.
  68. int32 line; //<! Line number in the source file.
  69. };
  70. /// Kaldi fatal runtime error exception. This exception is thrown from any use
  71. /// of the KALDI_ERR logging macro after the logging function, either set by
  72. /// SetLogHandler(), or the Kaldi's internal one, has returned.
  73. class KaldiFatalError : public std::runtime_error {
  74. public:
  75. explicit KaldiFatalError(const std::string &message)
  76. : std::runtime_error(message) {}
  77. explicit KaldiFatalError(const char *message) : std::runtime_error(message) {}
  78. /// Returns the exception name, "kaldi::KaldiFatalError".
  79. virtual const char *what() const noexcept override {
  80. return "kaldi::KaldiFatalError";
  81. }
  82. /// Returns the Kaldi error message logged by KALDI_ERR.
  83. const char *KaldiMessage() const { return std::runtime_error::what(); }
  84. };
  85. // Class MessageLogger is the workhorse behind the KALDI_ASSERT, KALDI_ERR,
  86. // KALDI_WARN, KALDI_LOG and KALDI_VLOG macros. It formats the message, then
  87. // either prints it to stderr or passes to the custom logging handler if
  88. // provided. Then, in case of the error, throws a KaldiFatalError exception, or
  89. // in case of failed KALDI_ASSERT, calls std::abort().
  90. class MessageLogger {
  91. public:
  92. /// The constructor stores the message's "envelope", a set of data which
  93. // identifies the location in source which is sending the message to log.
  94. // The pointers to strings are stored internally, and not owned or copied,
  95. // so that their storage must outlive this object.
  96. MessageLogger(LogMessageEnvelope::Severity severity, const char *func,
  97. const char *file, int32 line);
  98. // The stream insertion operator, used in e.g. 'KALDI_LOG << "Message"'.
  99. template <typename T> MessageLogger &operator<<(const T &val) {
  100. ss_ << val;
  101. return *this;
  102. }
  103. // When assigned a MessageLogger, log its contents.
  104. struct Log final {
  105. void operator=(const MessageLogger &logger) { logger.LogMessage(); }
  106. };
  107. // When assigned a MessageLogger, log its contents and then throw
  108. // a KaldiFatalError.
  109. struct LogAndThrow final {
  110. [[noreturn]] void operator=(const MessageLogger &logger) {
  111. logger.LogMessage();
  112. throw KaldiFatalError(logger.GetMessage());
  113. }
  114. };
  115. private:
  116. std::string GetMessage() const { return ss_.str(); }
  117. void LogMessage() const;
  118. LogMessageEnvelope envelope_;
  119. std::ostringstream ss_;
  120. };
  121. // Logging macros.
  122. #define KALDI_ERR \
  123. ::kaldi::MessageLogger::LogAndThrow() = ::kaldi::MessageLogger( \
  124. ::kaldi::LogMessageEnvelope::kError, __func__, __FILE__, __LINE__)
  125. #define KALDI_WARN \
  126. ::kaldi::MessageLogger::Log() = ::kaldi::MessageLogger( \
  127. ::kaldi::LogMessageEnvelope::kWarning, __func__, __FILE__, __LINE__)
  128. #define KALDI_LOG \
  129. ::kaldi::MessageLogger::Log() = ::kaldi::MessageLogger( \
  130. ::kaldi::LogMessageEnvelope::kInfo, __func__, __FILE__, __LINE__)
  131. #define KALDI_VLOG(v) \
  132. if ((v) <= ::kaldi::GetVerboseLevel()) \
  133. ::kaldi::MessageLogger::Log() = \
  134. ::kaldi::MessageLogger((::kaldi::LogMessageEnvelope::Severity)(v), \
  135. __func__, __FILE__, __LINE__)
  136. /***** KALDI ASSERTS *****/
  137. [[noreturn]] void KaldiAssertFailure_(const char *func, const char *file,
  138. int32 line, const char *cond_str);
  139. // Note on KALDI_ASSERT and KALDI_PARANOID_ASSERT:
  140. //
  141. // A single block {} around if /else does not work, because it causes
  142. // syntax error (unmatched else block) in the following code:
  143. //
  144. // if (condition)
  145. // KALDI_ASSERT(condition2);
  146. // else
  147. // SomethingElse();
  148. //
  149. // do {} while(0) -- note there is no semicolon at the end! -- works nicely,
  150. // and compilers will be able to optimize the loop away (as the condition
  151. // is always false).
  152. //
  153. // Also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h, and
  154. // KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE, also defined
  155. // there.
  156. #ifndef NDEBUG
  157. #define KALDI_ASSERT(cond) \
  158. do { \
  159. if (cond) \
  160. (void)0; \
  161. else \
  162. ::kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond); \
  163. } while (0)
  164. #else
  165. #define KALDI_ASSERT(cond) (void)0
  166. #endif
  167. // Some more expensive asserts only checked if this defined.
  168. #ifdef KALDI_PARANOID
  169. #define KALDI_PARANOID_ASSERT(cond) \
  170. do { \
  171. if (cond) \
  172. (void)0; \
  173. else \
  174. ::kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond); \
  175. } while (0)
  176. #else
  177. #define KALDI_PARANOID_ASSERT(cond) (void)0
  178. #endif
  179. /***** THIRD-PARTY LOG-HANDLER *****/
  180. /// Type of third-party logging function.
  181. typedef void (*LogHandler)(const LogMessageEnvelope &envelope,
  182. const char *message);
  183. /// Set logging handler. If called with a non-NULL function pointer, the
  184. /// function pointed by it is called to send messages to a caller-provided log.
  185. /// If called with a NULL pointer, restores default Kaldi error logging to
  186. /// stderr. This function is obviously not thread safe; the log handler must be.
  187. /// Returns a previously set logging handler pointer, or NULL.
  188. LogHandler SetLogHandler(LogHandler);
  189. /// @} end "addtogroup error_group"
  190. //// Functions within internal is exported for testing only, do not use.
  191. //namespace internal {
  192. //bool LocateSymbolRange(const std::string &trace_name, size_t *begin,
  193. // size_t *end);
  194. //} // namespace internal
  195. } // namespace kaldi
  196. #endif // KALDI_BASE_KALDI_ERROR_H_