зеркало из https://github.com/mozilla/kaldi.git
Merge pull request #755 from vesis84/error_logs
base/kaldi_error : the error messages are no longer printed 2x
This commit is contained in:
Коммит
ea7f04b244
|
@ -1,5 +1,6 @@
|
||||||
// base/kaldi-error.cc
|
// base/kaldi-error.cc
|
||||||
|
|
||||||
|
// Copyright 2016 Brno University of Technology (author: Karel Vesely)
|
||||||
// Copyright 2009-2011 Microsoft Corporation; Lukas Burget; Ondrej Glembek
|
// Copyright 2009-2011 Microsoft Corporation; Lukas Burget; Ondrej Glembek
|
||||||
|
|
||||||
// See ../../COPYING for clarification regarding multiple authors
|
// See ../../COPYING for clarification regarding multiple authors
|
||||||
|
@ -20,8 +21,8 @@
|
||||||
#ifdef HAVE_EXECINFO_H
|
#ifdef HAVE_EXECINFO_H
|
||||||
#include <execinfo.h> // To get stack trace in error messages.
|
#include <execinfo.h> // To get stack trace in error messages.
|
||||||
// If this #include fails there is an error in the Makefile, it does not
|
// If this #include fails there is an error in the Makefile, it does not
|
||||||
// support your platform well. Make sure HAVE_EXECINFO_H is undefined, and the
|
// support your platform well. Make sure HAVE_EXECINFO_H is undefined,
|
||||||
// code will compile.
|
// and the code will compile.
|
||||||
#ifdef HAVE_CXXABI_H
|
#ifdef HAVE_CXXABI_H
|
||||||
#include <cxxabi.h> // For name demangling.
|
#include <cxxabi.h> // For name demangling.
|
||||||
// Useful to decode the stack trace, but only used if we have execinfo.h
|
// Useful to decode the stack trace, but only used if we have execinfo.h
|
||||||
|
@ -32,11 +33,13 @@
|
||||||
#include "base/kaldi-error.h"
|
#include "base/kaldi-error.h"
|
||||||
|
|
||||||
namespace kaldi {
|
namespace kaldi {
|
||||||
|
|
||||||
|
/***** GLOBAL VARIABLES FOR LOGGING *****/
|
||||||
|
|
||||||
int32 g_kaldi_verbose_level = 0;
|
int32 g_kaldi_verbose_level = 0;
|
||||||
const char *g_program_name = NULL;
|
const char *g_program_name = NULL;
|
||||||
static LogHandler g_log_handler = NULL;
|
static LogHandler g_log_handler = NULL;
|
||||||
|
|
||||||
|
|
||||||
// If the program name was set (g_program_name != ""), the function
|
// If the program name was set (g_program_name != ""), the function
|
||||||
// GetProgramName returns the program name (without the path) followed by a
|
// GetProgramName returns the program name (without the path) followed by a
|
||||||
// colon, e.g. "gmm-align:". Otherwise it returns the empty string "".
|
// colon, e.g. "gmm-align:". Otherwise it returns the empty string "".
|
||||||
|
@ -44,10 +47,13 @@ const char *GetProgramName() {
|
||||||
return g_program_name == NULL ? "" : g_program_name;
|
return g_program_name == NULL ? "" : g_program_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** HELPER FUNCTIONS *****/
|
||||||
|
|
||||||
// Given a filename like "/a/b/c/d/e/f.cc", GetShortFileName
|
// Given a filename like "/a/b/c/d/e/f.cc", GetShortFileName
|
||||||
// returns "e/f.cc". Does not currently work if backslash is
|
// returns "e/f.cc". Does not currently work if backslash is
|
||||||
// the filename separator.
|
// the filename separator.
|
||||||
const char *GetShortFileName(const char *filename) {
|
static const char *GetShortFileName(const char *filename) {
|
||||||
const char *last_slash = strrchr(filename, '/');
|
const char *last_slash = strrchr(filename, '/');
|
||||||
if (!last_slash) {
|
if (!last_slash) {
|
||||||
return filename;
|
return filename;
|
||||||
|
@ -58,115 +64,78 @@ const char *GetShortFileName(const char *filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** STACKTRACE *****/
|
||||||
|
|
||||||
|
static std::string Demangle(std::string trace_name) {
|
||||||
#if defined(HAVE_CXXABI_H) && defined(HAVE_EXECINFO_H)
|
#if defined(HAVE_CXXABI_H) && defined(HAVE_EXECINFO_H)
|
||||||
// The function name looks like a macro: it's a macro if we don't have ccxxabi.h
|
// at input the string looks like:
|
||||||
inline void KALDI_APPEND_POSSIBLY_DEMANGLED_STRING(const char *to_append,
|
|
||||||
std::string *ans) {
|
|
||||||
// at input the string "to_append" looks like:
|
|
||||||
// ./kaldi-error-test(_ZN5kaldi13UnitTestErrorEv+0xb) [0x804965d]
|
// ./kaldi-error-test(_ZN5kaldi13UnitTestErrorEv+0xb) [0x804965d]
|
||||||
// We want to extract the name e.g. '_ZN5kaldi13UnitTestErrorEv",
|
// We want to extract the name e.g. '_ZN5kaldi13UnitTestErrorEv",
|
||||||
// demangle it and return it.
|
// demangle it and return it.
|
||||||
int32 status;
|
|
||||||
const char *paren = strchr(to_append, '(');
|
// try to locate '(' and '+', take the string in between,
|
||||||
const char *plus = (paren ? strchr(paren, '+') : NULL);
|
size_t begin(trace_name.find("(")),
|
||||||
if (!plus) { // did not find the '(' or did not find the '+'
|
end(trace_name.rfind("+"));
|
||||||
// This is a soft failure in case we did not get what we expected.
|
if (begin != std::string::npos && end != std::string::npos && begin < end) {
|
||||||
ans->append(to_append);
|
trace_name = trace_name.substr(begin+1,end-(begin+1));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
std::string stripped(paren+1, plus-(paren+1)); // the bit between ( and +.
|
// demangle,
|
||||||
|
int status;
|
||||||
char *demangled_name = abi::__cxa_demangle(stripped.c_str(), 0, 0, &status);
|
char *demangled_name = abi::__cxa_demangle(trace_name.c_str(), 0, 0, &status);
|
||||||
|
std::string ans;
|
||||||
// if status != 0 it is an error (demangling failure), but not all names seem
|
if (status == 0) {
|
||||||
// to demangle, so we don't check it.
|
ans = demangled_name;
|
||||||
|
|
||||||
if (demangled_name != NULL) {
|
|
||||||
ans->append(demangled_name);
|
|
||||||
free(demangled_name);
|
free(demangled_name);
|
||||||
} else {
|
} else {
|
||||||
ans->append(to_append); // add the original string.
|
ans = trace_name;
|
||||||
}
|
}
|
||||||
|
// return,
|
||||||
|
return ans;
|
||||||
|
#else
|
||||||
|
return trace_name;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else // defined(HAVE_CXXABI_H) && defined(HAVE_EXECINFO_H)
|
|
||||||
#define KALDI_APPEND_POSSIBLY_DEMANGLED_STRING(to_append, ans) \
|
|
||||||
ans->append(to_append)
|
|
||||||
#endif // defined(HAVE_CXXABI_H) && defined(HAVE_EXECINFO_H)
|
|
||||||
|
|
||||||
|
|
||||||
|
static std::string KaldiGetStackTrace() {
|
||||||
|
std::string ans;
|
||||||
#ifdef HAVE_EXECINFO_H
|
#ifdef HAVE_EXECINFO_H
|
||||||
std::string KaldiGetStackTrace() {
|
|
||||||
#define KALDI_MAX_TRACE_SIZE 50
|
#define KALDI_MAX_TRACE_SIZE 50
|
||||||
#define KALDI_MAX_TRACE_PRINT 20 // must be even.
|
#define KALDI_MAX_TRACE_PRINT 20 // must be even.
|
||||||
std::string ans;
|
// buffer for the trace,
|
||||||
void *array[KALDI_MAX_TRACE_SIZE];
|
void *trace[KALDI_MAX_TRACE_SIZE];
|
||||||
size_t size = backtrace(array, KALDI_MAX_TRACE_SIZE);
|
// get the trace,
|
||||||
char **strings = backtrace_symbols(array, size);
|
size_t size = backtrace(trace, KALDI_MAX_TRACE_SIZE);
|
||||||
|
// get the trace symbols,
|
||||||
|
char **trace_symbol = backtrace_symbols(trace, size);
|
||||||
|
|
||||||
|
// Compose the 'string',
|
||||||
|
ans += "[ Stack-Trace: ]\n";
|
||||||
if (size <= KALDI_MAX_TRACE_PRINT) {
|
if (size <= KALDI_MAX_TRACE_PRINT) {
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
KALDI_APPEND_POSSIBLY_DEMANGLED_STRING(strings[i], &ans);
|
ans += Demangle(trace_symbol[i]) + "\n";
|
||||||
ans += "\n";
|
|
||||||
}
|
}
|
||||||
} else { // print out first+last (e.g.) 5.
|
} else { // print out first+last (e.g.) 5.
|
||||||
for (size_t i = 0; i < KALDI_MAX_TRACE_PRINT/2; i++) {
|
for (size_t i = 0; i < KALDI_MAX_TRACE_PRINT/2; i++) {
|
||||||
KALDI_APPEND_POSSIBLY_DEMANGLED_STRING(strings[i], &ans);
|
ans += Demangle(trace_symbol[i]) + "\n";
|
||||||
ans += "\n";
|
|
||||||
}
|
}
|
||||||
ans += ".\n.\n.\n";
|
ans += ".\n.\n.\n";
|
||||||
for (size_t i = size - KALDI_MAX_TRACE_PRINT/2; i < size; i++) {
|
for (size_t i = size - KALDI_MAX_TRACE_PRINT/2; i < size; i++) {
|
||||||
KALDI_APPEND_POSSIBLY_DEMANGLED_STRING(strings[i], &ans);
|
ans += Demangle(trace_symbol[i]) + "\n";
|
||||||
ans += "\n";
|
|
||||||
}
|
}
|
||||||
if (size == KALDI_MAX_TRACE_SIZE)
|
if (size == KALDI_MAX_TRACE_SIZE)
|
||||||
ans += ".\n.\n.\n"; // stack was too long, probably a bug.
|
ans += ".\n.\n.\n"; // stack was too long, probably a bug.
|
||||||
}
|
}
|
||||||
free(strings); // it's all in one big malloc()ed block.
|
|
||||||
|
|
||||||
|
// cleanup,
|
||||||
#ifdef HAVE_CXXABI_H // demangle the name, if possible.
|
free(trace_symbol); // it's okay, just the pointers, not the strings.
|
||||||
#endif // HAVE_CXXABI_H
|
#endif // HAVE_EXECINFO_H
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void KaldiAssertFailure_(const char *func, const char *file,
|
|
||||||
int32 line, const char *cond_str) {
|
|
||||||
MessageLogger ml(LogMessageEnvelope::Error, func, file, line);
|
|
||||||
ml.stream() << "Assertion failed: " << cond_str;
|
|
||||||
#ifdef HAVE_EXECINFO_H
|
|
||||||
ml.stream() << "\nStack trace is:\n" << KaldiGetStackTrace();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
LogHandler SetLogHandler(LogHandler new_handler) {
|
/***** KALDI LOGIGNG *****/
|
||||||
LogHandler old_handler = g_log_handler;
|
|
||||||
g_log_handler = new_handler;
|
|
||||||
return old_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SendToLog(const LogMessageEnvelope &envelope,
|
|
||||||
const char *message) {
|
|
||||||
// Send to a logging handler if provided.
|
|
||||||
if (g_log_handler != NULL) {
|
|
||||||
g_log_handler(envelope, message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, use Kaldi default logging.
|
|
||||||
std::stringstream header;
|
|
||||||
if (envelope.severity > LogMessageEnvelope::Info)
|
|
||||||
header << "VLOG[" << envelope.severity << "] (";
|
|
||||||
else if (envelope.severity == LogMessageEnvelope::Info)
|
|
||||||
header << "LOG (";
|
|
||||||
else if (envelope.severity == LogMessageEnvelope::Warning)
|
|
||||||
header << "WARNING (";
|
|
||||||
else
|
|
||||||
header << "ERROR (";
|
|
||||||
header << GetProgramName() << envelope.func << "():"
|
|
||||||
<< envelope.file << ':' << envelope.line << ")";
|
|
||||||
|
|
||||||
std::string header_str = header.str();
|
|
||||||
fprintf(stderr, "%s %s\n", header_str.c_str(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageLogger::MessageLogger(LogMessageEnvelope::Severity severity,
|
MessageLogger::MessageLogger(LogMessageEnvelope::Severity severity,
|
||||||
const char *func, const char *file, int32 line) {
|
const char *func, const char *file, int32 line) {
|
||||||
|
@ -177,27 +146,99 @@ MessageLogger::MessageLogger(LogMessageEnvelope::Severity severity,
|
||||||
envelope_.line = line;
|
envelope_.line = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MessageLogger::~MessageLogger() KALDI_NOEXCEPT(false) {
|
MessageLogger::~MessageLogger() KALDI_NOEXCEPT(false) {
|
||||||
|
// remove trailing '\n',
|
||||||
std::string str = ss_.str();
|
std::string str = ss_.str();
|
||||||
while (!str.empty() && str[str.length() - 1] == '\n')
|
while (!str.empty() && str[str.length() - 1] == '\n')
|
||||||
str.resize(str.length() - 1);
|
str.resize(str.length() - 1);
|
||||||
SendToLog(envelope_, str.c_str());
|
|
||||||
|
|
||||||
if (envelope_.severity > LogMessageEnvelope::Error)
|
// print the mesage (or send to logging handler),
|
||||||
return;
|
MessageLogger::HandleMessage(envelope_, str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// On error, throw an exception with the message, plus traceback info if
|
|
||||||
// available.
|
void MessageLogger::HandleMessage(const LogMessageEnvelope &envelope,
|
||||||
if (!std::uncaught_exception()) {
|
const char *message) {
|
||||||
#ifdef HAVE_EXECINFO_H
|
// Send to a logging handler if provided.
|
||||||
throw std::runtime_error(str + "\n\n[stack trace: ]\n" +
|
if (g_log_handler != NULL) {
|
||||||
KaldiGetStackTrace() + "\n");
|
g_log_handler(envelope, message);
|
||||||
#else
|
|
||||||
throw std::runtime_error(str);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
abort();
|
// Otherwise, we use the default Kaldi logging.
|
||||||
|
// Build the log-message 'header',
|
||||||
|
std::stringstream header;
|
||||||
|
if (envelope.severity > LogMessageEnvelope::kInfo) {
|
||||||
|
header << "VLOG[" << envelope.severity << "] (";
|
||||||
|
} else {
|
||||||
|
switch (envelope.severity) {
|
||||||
|
case LogMessageEnvelope::kInfo :
|
||||||
|
header << "LOG (";
|
||||||
|
break;
|
||||||
|
case LogMessageEnvelope::kWarning :
|
||||||
|
header << "WARNING (";
|
||||||
|
break;
|
||||||
|
case LogMessageEnvelope::kError :
|
||||||
|
header << "ERROR (";
|
||||||
|
break;
|
||||||
|
case LogMessageEnvelope::kAssertFailed :
|
||||||
|
header << "ASSERTION_FAILED (";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(); // coding errror (unknown 'severity'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill the other info from the envelope,
|
||||||
|
header << GetProgramName() << envelope.func << "():"
|
||||||
|
<< envelope.file << ':' << envelope.line << ")";
|
||||||
|
|
||||||
|
// Printing the message,
|
||||||
|
if (envelope.severity >= LogMessageEnvelope::kWarning) {
|
||||||
|
// VLOG, LOG, WARNING:
|
||||||
|
fprintf(stderr, "%s %s\n", header.str().c_str(), message);
|
||||||
|
} else {
|
||||||
|
// ERROR, ASSERT_FAILED (print with stack-trace):
|
||||||
|
fprintf(stderr, "%s %s\n\n%s\n", header.str().c_str(), message,
|
||||||
|
KaldiGetStackTrace().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should we throw exception, or abort?
|
||||||
|
switch (envelope.severity) {
|
||||||
|
case LogMessageEnvelope::kAssertFailed:
|
||||||
|
abort(); // ASSERT_FAILED,
|
||||||
|
break;
|
||||||
|
case LogMessageEnvelope::kError:
|
||||||
|
if (!std::uncaught_exception()) {
|
||||||
|
// throw exception with empty message,
|
||||||
|
throw std::runtime_error(""); // KALDI_ERR,
|
||||||
|
} else {
|
||||||
|
// If we got here, this thread has already thrown exception,
|
||||||
|
// and this exception has not yet arrived to its 'catch' clause...
|
||||||
|
// Throwing a new exception would be unsafe!
|
||||||
|
// (can happen during 'stack unwinding', if we have 'KALDI_ERR << msg'
|
||||||
|
// in a destructor of some local object).
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** KALDI ASSERTS *****/
|
||||||
|
|
||||||
|
void KaldiAssertFailure_(const char *func, const char *file,
|
||||||
|
int32 line, const char *cond_str) {
|
||||||
|
MessageLogger ml(LogMessageEnvelope::kAssertFailed, func, file, line);
|
||||||
|
ml.stream() << ": '" << cond_str << "' ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** THIRD-PARTY LOG-HANDLER *****/
|
||||||
|
|
||||||
|
LogHandler SetLogHandler(LogHandler new_handler) {
|
||||||
|
LogHandler old_handler = g_log_handler;
|
||||||
|
g_log_handler = new_handler;
|
||||||
|
return old_handler;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace kaldi
|
} // end namespace kaldi
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// base/kaldi-error.h
|
// base/kaldi-error.h
|
||||||
|
|
||||||
|
// Copyright 2016 Brno University of Technology (author: Karel Vesely)
|
||||||
// Copyright 2009-2011 Microsoft Corporation; Ondrej Glembek; Lukas Burget;
|
// Copyright 2009-2011 Microsoft Corporation; Ondrej Glembek; Lukas Burget;
|
||||||
// Saarland University
|
// Saarland University
|
||||||
|
|
||||||
|
@ -29,13 +30,15 @@
|
||||||
|
|
||||||
#include "base/kaldi-types.h"
|
#include "base/kaldi-types.h"
|
||||||
#include "base/kaldi-utils.h"
|
#include "base/kaldi-utils.h"
|
||||||
|
|
||||||
/* Important that this file does not depend on any other kaldi headers. */
|
/* Important that this file does not depend on any other kaldi headers. */
|
||||||
|
|
||||||
|
// By adding 'KALDI_NOEXCEPT(bool)' immediately after function declaration,
|
||||||
|
// we can tell the compiler that the function must-not produce
|
||||||
|
// exceptions (true), or may produce exceptions (false):
|
||||||
#if _MSC_VER >= 1900 || (!defined(_MSC_VER) && __cplusplus >= 201103L)
|
#if _MSC_VER >= 1900 || (!defined(_MSC_VER) && __cplusplus >= 201103L)
|
||||||
#define KALDI_NOEXCEPT(Predicate) noexcept((Predicate))
|
#define KALDI_NOEXCEPT(Predicate) noexcept((Predicate))
|
||||||
#elif defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
#elif defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
||||||
(__GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
|
(__GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
|
||||||
#define KALDI_NOEXCEPT(Predicate) noexcept((Predicate))
|
#define KALDI_NOEXCEPT(Predicate) noexcept((Predicate))
|
||||||
#else
|
#else
|
||||||
#define KALDI_NOEXCEPT(Predicate)
|
#define KALDI_NOEXCEPT(Predicate)
|
||||||
|
@ -50,7 +53,9 @@ namespace kaldi {
|
||||||
/// \addtogroup error_group
|
/// \addtogroup error_group
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// This is set by util/parse-options.{h, cc} if you set --verbose = ? option.
|
/***** VERBOSITY LEVEL *****/
|
||||||
|
|
||||||
|
/// This is set by util/parse-options.{h, cc} if you set --verbose=? option.
|
||||||
extern int32 g_kaldi_verbose_level;
|
extern int32 g_kaldi_verbose_level;
|
||||||
|
|
||||||
/// This is set by util/parse-options.{h, cc} (from argv[0]) and used (if set)
|
/// This is set by util/parse-options.{h, cc} (from argv[0]) and used (if set)
|
||||||
|
@ -66,12 +71,16 @@ inline int32 GetVerboseLevel() { return g_kaldi_verbose_level; }
|
||||||
/// automatically from ParseOptions.
|
/// automatically from ParseOptions.
|
||||||
inline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }
|
inline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }
|
||||||
|
|
||||||
|
|
||||||
|
/***** KALDI LOGGING *****/
|
||||||
|
|
||||||
/// Log message severity and source location info.
|
/// Log message severity and source location info.
|
||||||
struct LogMessageEnvelope {
|
struct LogMessageEnvelope {
|
||||||
enum Severity {
|
enum Severity {
|
||||||
Error = -2,
|
kAssertFailed = -3,
|
||||||
Warning = -1,
|
kError = -2,
|
||||||
Info = 0,
|
kWarning = -1,
|
||||||
|
kInfo = 0,
|
||||||
};
|
};
|
||||||
// An 'enum Severity' value, or a positive number indicating verbosity level.
|
// An 'enum Severity' value, or a positive number indicating verbosity level.
|
||||||
int severity;
|
int severity;
|
||||||
|
@ -80,36 +89,59 @@ struct LogMessageEnvelope {
|
||||||
int32 line;
|
int32 line;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Type of user-provided logging function.
|
// Class MessageLogger is invoked from the KALDI_ASSERT, KALDI_ERR, KALDI_WARN and
|
||||||
typedef void (*LogHandler)(const LogMessageEnvelope &envelope,
|
|
||||||
const char *message);
|
|
||||||
|
|
||||||
/// Set logging handler. If called with a non-NULL function pointer, the
|
|
||||||
/// function pointed by it is called to send messages to a caller-provided
|
|
||||||
/// log. If called with NULL pointer, restores default Kaldi error logging to
|
|
||||||
/// stderr. SetLogHandler is obviously not thread safe.
|
|
||||||
LogHandler SetLogHandler(LogHandler);
|
|
||||||
|
|
||||||
// Class MessageLogger is invoked from the KALDI_ERR, KALDI_WARN, KALDI_LOG and
|
|
||||||
// KALDI_LOG macros. It formats the message, then either prints it to stderr or
|
// KALDI_LOG macros. It formats the message, then either prints it to stderr or
|
||||||
// passes to the log custom handler if provided, then, in case of the error,
|
// passes to the log custom handler if provided, then, in case of the error,
|
||||||
// throws an std::runtime_exception.
|
// throws an std::runtime_exception, in case of failed KALDI_ASSERT calls abort().
|
||||||
//
|
//
|
||||||
// Note: we avoid using std::cerr, since it does not guarantee thread safety
|
// Note: we avoid using std::cerr for thread safety issues.
|
||||||
// in general, until C++11; even then, in "cerr << a << b", other thread's
|
// fprintf(stderr,...) is guaranteed thread-safe, and outputs
|
||||||
// output is allowed to intrude between a and b. fprintf(stderr,...) is
|
// its formatted string atomically.
|
||||||
// guaranteed thread-safe, and outputs its formatted string atomically.
|
|
||||||
class MessageLogger {
|
class MessageLogger {
|
||||||
public:
|
public:
|
||||||
MessageLogger(LogMessageEnvelope::Severity severity, const char *func,
|
/// Constructor stores the info,
|
||||||
const char *file, int32 line);
|
MessageLogger(LogMessageEnvelope::Severity severity,
|
||||||
|
const char *func,
|
||||||
|
const char *file,
|
||||||
|
int32 line);
|
||||||
|
|
||||||
|
/// Destructor, calls 'HandleMessage' which prints the message,
|
||||||
|
/// (since C++11 a 'throwing' destructor must be declared 'noexcept(false)')
|
||||||
~MessageLogger() KALDI_NOEXCEPT(false);
|
~MessageLogger() KALDI_NOEXCEPT(false);
|
||||||
|
|
||||||
|
/// The hook for the 'insertion operator', e.g.
|
||||||
|
/// 'KALDI_LOG << "Message,"',
|
||||||
inline std::ostream &stream() { return ss_; }
|
inline std::ostream &stream() { return ss_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// The logging function,
|
||||||
|
static void HandleMessage(const LogMessageEnvelope &env, const char *msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LogMessageEnvelope envelope_;
|
LogMessageEnvelope envelope_;
|
||||||
std::ostringstream ss_;
|
std::ostringstream ss_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The definition of the logging macros,
|
||||||
|
#define KALDI_ERR \
|
||||||
|
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::kError, \
|
||||||
|
__func__, __FILE__, __LINE__).stream()
|
||||||
|
#define KALDI_WARN \
|
||||||
|
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::kWarning, \
|
||||||
|
__func__, __FILE__, __LINE__).stream()
|
||||||
|
#define KALDI_LOG \
|
||||||
|
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::kInfo, \
|
||||||
|
__func__, __FILE__, __LINE__).stream()
|
||||||
|
#define KALDI_VLOG(v) if ((v) <= ::kaldi::g_kaldi_verbose_level) \
|
||||||
|
::kaldi::MessageLogger((::kaldi::LogMessageEnvelope::Severity)(v), \
|
||||||
|
__func__, __FILE__, __LINE__).stream()
|
||||||
|
|
||||||
|
|
||||||
|
/***** KALDI ASSERTS *****/
|
||||||
|
|
||||||
|
void KaldiAssertFailure_(const char *func, const char *file,
|
||||||
|
int32 line, const char *cond_str);
|
||||||
|
|
||||||
// Note on KALDI_ASSERT and KALDI_PARANOID_ASSERT
|
// Note on KALDI_ASSERT and KALDI_PARANOID_ASSERT
|
||||||
// The original (simple) version of the code was this
|
// The original (simple) version of the code was this
|
||||||
//
|
//
|
||||||
|
@ -138,7 +170,7 @@ private:
|
||||||
#else
|
#else
|
||||||
#define KALDI_ASSERT(cond) (void)0
|
#define KALDI_ASSERT(cond) (void)0
|
||||||
#endif
|
#endif
|
||||||
// also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h,
|
// Also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h,
|
||||||
// and KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE,
|
// and KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE,
|
||||||
// also defined there.
|
// also defined there.
|
||||||
// some more expensive asserts only checked if this defined
|
// some more expensive asserts only checked if this defined
|
||||||
|
@ -150,25 +182,17 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define KALDI_ERR \
|
/***** THIRD-PARTY LOG-HANDLER *****/
|
||||||
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::Error, \
|
|
||||||
__func__, __FILE__, __LINE__).stream()
|
|
||||||
#define KALDI_WARN \
|
|
||||||
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::Warning, \
|
|
||||||
__func__, __FILE__, __LINE__).stream()
|
|
||||||
#define KALDI_LOG \
|
|
||||||
::kaldi::MessageLogger(::kaldi::LogMessageEnvelope::Info, \
|
|
||||||
__func__, __FILE__, __LINE__).stream()
|
|
||||||
#define KALDI_VLOG(v) if ((v) <= ::kaldi::g_kaldi_verbose_level) \
|
|
||||||
::kaldi::MessageLogger((::kaldi::LogMessageEnvelope::Severity)(v), \
|
|
||||||
__func__, __FILE__, __LINE__).stream()
|
|
||||||
|
|
||||||
inline bool IsKaldiError(const std::string &str) {
|
/// Type of third-party logging function,
|
||||||
return(!strncmp(str.c_str(), "ERROR ", 6));
|
typedef void (*LogHandler)(const LogMessageEnvelope &envelope,
|
||||||
}
|
const char *message);
|
||||||
|
|
||||||
void KaldiAssertFailure_(const char *func, const char *file,
|
/// Set logging handler. If called with a non-NULL function pointer, the
|
||||||
int32 line, const char *cond_str);
|
/// function pointed by it is called to send messages to a caller-provided
|
||||||
|
/// log. If called with NULL pointer, restores default Kaldi error logging to
|
||||||
|
/// stderr. SetLogHandler is obviously not thread safe.
|
||||||
|
LogHandler SetLogHandler(LogHandler);
|
||||||
|
|
||||||
/// @} end "addtogroup error_group"
|
/// @} end "addtogroup error_group"
|
||||||
|
|
||||||
|
|
|
@ -135,8 +135,8 @@ class WaveHolder {
|
||||||
t.Write(os); // throws exception on failure.
|
t.Write(os); // throws exception on failure.
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught in WaveHolder object (writing).";
|
KALDI_WARN << "Exception caught in WaveHolder object (writing). "
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
<< e.what();
|
||||||
return false; // write failure.
|
return false; // write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,8 +162,8 @@ class WaveHolder {
|
||||||
t_.Read(is); // throws exception on failure.
|
t_.Read(is); // throws exception on failure.
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught in WaveHolder object (reading).";
|
KALDI_WARN << "Exception caught in WaveHolder object (reading). "
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
<< e.what();
|
||||||
return false; // write failure.
|
return false; // write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,8 +213,8 @@ class WaveInfoHolder {
|
||||||
t_.Read(is, WaveData::kLeaveDataUndefined); // throws exception on failure.
|
t_.Read(is, WaveData::kLeaveDataUndefined); // throws exception on failure.
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught in WaveHolder object (reading).";
|
KALDI_WARN << "Exception caught in WaveHolder object (reading). "
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
<< e.what();
|
||||||
return false; // write failure.
|
return false; // write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,8 +129,7 @@ bool PosteriorHolder::Write(std::ostream &os, bool binary, const T &t) {
|
||||||
WritePosterior(os, binary, t);
|
WritePosterior(os, binary, t);
|
||||||
return true;
|
return true;
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing table of posteriors";
|
KALDI_WARN << "Exception caught writing table of posteriors. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,8 +146,7 @@ bool PosteriorHolder::Read(std::istream &is) {
|
||||||
ReadPosterior(is, is_binary, &t_);
|
ReadPosterior(is, is_binary, &t_);
|
||||||
return true;
|
return true;
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught reading table of posteriors";
|
KALDI_WARN << "Exception caught reading table of posteriors. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
t_.clear();
|
t_.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -174,8 +172,7 @@ bool GaussPostHolder::Write(std::ostream &os, bool binary, const T &t) {
|
||||||
if(!binary) os << '\n';
|
if(!binary) os << '\n';
|
||||||
return os.good();
|
return os.good();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing table of posteriors";
|
KALDI_WARN << "Exception caught writing table of posteriors. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,8 +207,7 @@ bool GaussPostHolder::Read(std::istream &is) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught reading table of posteriors";
|
KALDI_WARN << "Exception caught reading table of posteriors. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
t_.clear();
|
t_.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,7 @@ template<class KaldiType> class KaldiObjectHolder {
|
||||||
t.Write(os, binary);
|
t.Write(os, binary);
|
||||||
return os.good();
|
return os.good();
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing Table object: " << e.what();
|
KALDI_WARN << "Exception caught writing Table object. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,8 +79,7 @@ template<class KaldiType> class KaldiObjectHolder {
|
||||||
t_->Read(is, is_binary);
|
t_->Read(is, is_binary);
|
||||||
return true;
|
return true;
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught reading Table object ";
|
KALDI_WARN << "Exception caught reading Table object. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
delete t_;
|
delete t_;
|
||||||
t_ = NULL;
|
t_ = NULL;
|
||||||
return false;
|
return false;
|
||||||
|
@ -137,8 +135,7 @@ template<class BasicType> class BasicHolder {
|
||||||
// easier to manipulate.
|
// easier to manipulate.
|
||||||
return os.good();
|
return os.good();
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing Table object: " << e.what();
|
KALDI_WARN << "Exception caught writing Table object. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,8 +183,7 @@ template<class BasicType> class BasicHolder {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught reading Table object";
|
KALDI_WARN << "Exception caught reading Table object. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,8 +248,8 @@ template<class BasicType> class BasicVectorHolder {
|
||||||
}
|
}
|
||||||
return os.good();
|
return os.good();
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing Table object (BasicVector). ";
|
KALDI_WARN << "Exception caught writing Table object (BasicVector). "
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
<< e.what();
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,8 +286,7 @@ template<class BasicType> class BasicVectorHolder {
|
||||||
return true;
|
return true;
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "BasicVectorHolder::Read, could not interpret line: "
|
KALDI_WARN << "BasicVectorHolder::Read, could not interpret line: "
|
||||||
<< line;
|
<< "'" << line << "'" << "\n" << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else { // binary mode.
|
} else { // binary mode.
|
||||||
|
@ -390,8 +385,7 @@ template<class BasicType> class BasicVectorVectorHolder {
|
||||||
}
|
}
|
||||||
return os.good();
|
return os.good();
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing Table object. ";
|
KALDI_WARN << "Exception caught writing Table object. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,8 +430,7 @@ template<class BasicType> class BasicVectorVectorHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "BasicVectorVectorHolder::Read, read error";
|
KALDI_WARN << "BasicVectorVectorHolder::Read, read error. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else { // binary mode.
|
} else { // binary mode.
|
||||||
|
@ -532,8 +525,7 @@ template<class BasicType> class BasicPairVectorHolder {
|
||||||
}
|
}
|
||||||
return os.good();
|
return os.good();
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "Exception caught writing Table object. ";
|
KALDI_WARN << "Exception caught writing Table object. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false; // Write failure.
|
return false; // Write failure.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,8 +581,7 @@ template<class BasicType> class BasicPairVectorHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(const std::exception &e) {
|
} catch(const std::exception &e) {
|
||||||
KALDI_WARN << "BasicPairVectorHolder::Read, read error";
|
KALDI_WARN << "BasicPairVectorHolder::Read, read error. " << e.what();
|
||||||
if (!IsKaldiError(e.what())) { std::cerr << e.what(); }
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else { // binary mode.
|
} else { // binary mode.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче