creatable/writable.\r
o Added backwards compatibility (with deprecation warning) for using\r
thumbnails-path instead of thumbnail-path in casparcg.config.\r
+ o Suppress the logging of full path names in stack traces so that only the\r
+ relative path within the source tree is visible.\r
\r
AMCP\r
----\r
add_definitions( -DGLEW_NO_GLU )
add_definitions( "-DBOOST_ASIO_ERROR_CATEGORY_NOEXCEPT=noexcept(true)" ) # Workaround macro redefinition in boost
add_definitions( -D_GLIBCXX_USE_CXX11_ABI=0 ) # Allow compilation in GCC 5 while keeping old dependencies
+add_definitions( -DCASPAR_SOURCE_PREFIX="${CMAKE_CURRENT_SOURCE_DIR}" )
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa /Zi /W4 /WX /MP /fp:fast /Zm192 /FIcommon/compiler/vs/disable_silly_warnings.h")
#define CASPAR_VERIFY(expr) do{if(!(expr)){ CASPAR_LOG(warning) << "Assertion Failed: " << \
CASPAR_VERIFY_EXPR_STR(expr) << " " \
- << "file:" << __FILE__ << " " \
+ << "file:" << log::remove_source_prefix(__FILE__) << " " \
<< "line:" << __LINE__ << " "; \
_CASPAR_DBG_BREAK;\
}}while(0);
#define CASPAR_ASSERT(expr) CASPAR_VERIFY(expr)
#else
#define CASPAR_ASSERT(expr)
-#endif
\ No newline at end of file
+#endif
#include "utf.h"
#include "os/stack_trace.h"
+#include "log.h"
#include <exception>
#include <list>
typedef boost::error_info<struct tag_line_info, size_t> line_info;
typedef boost::error_info<struct tag_nested_exception_, std::exception_ptr> nested_exception;
-struct caspar_exception : virtual boost::exception, virtual std::exception
+struct caspar_exception : virtual boost::exception, virtual std::exception
{
caspar_exception(){}
const char* what() const throw() override
#define _CASPAR_GENERATE_UNIQUE_IDENTIFIER(name, line) _CASPAR_GENERATE_UNIQUE_IDENTIFIER_CAT(name, line)
#define CASPAR_SCOPED_CONTEXT_MSG(ctx_msg) ::caspar::scoped_context _CASPAR_GENERATE_UNIQUE_IDENTIFIER(SCOPED_CONTEXT, __LINE__)(u8(ctx_msg));
-#define CASPAR_THROW_EXCEPTION(e) BOOST_THROW_EXCEPTION(e << call_stack_info(caspar::get_call_stack()) << context_info(get_context()))
+#define CASPAR_THROW_EXCEPTION(e) ::boost::exception_detail::throw_exception_((e << call_stack_info(caspar::get_call_stack()) << context_info(get_context())), BOOST_THROW_EXCEPTION_CURRENT_FUNCTION, ::caspar::log::remove_source_prefix(__FILE__), __LINE__)
std::string get_message_and_context(const caspar_exception& e);
}
-
#include <GL/glew.h>
-namespace caspar { namespace gl {
+namespace caspar { namespace gl {
-void SMFL_GLCheckError(const std::string&, const std::string& file, unsigned int line)
+void SMFL_GLCheckError(const std::string&, const char* func, const char* file, unsigned int line)
{
// Get the last error
GLenum LastErrorCode = GL_NO_ERROR;
switch (LastErrorCode)
{
case GL_INVALID_ENUM :
- CASPAR_THROW_EXCEPTION(ogl_invalid_enum()
- << msg_info("an unacceptable value has been specified for an enumerated argument")
- << error_info("GL_INVALID_ENUM")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_invalid_enum()
+ << msg_info("an unacceptable value has been specified for an enumerated argument")
+ << error_info("GL_INVALID_ENUM")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
case GL_INVALID_VALUE :
- CASPAR_THROW_EXCEPTION(ogl_invalid_value()
- << msg_info("a numeric argument is out of range")
- << error_info("GL_INVALID_VALUE")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_invalid_value()
+ << msg_info("a numeric argument is out of range")
+ << error_info("GL_INVALID_VALUE")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
case GL_INVALID_OPERATION :
- CASPAR_THROW_EXCEPTION(ogl_invalid_operation()
- << msg_info("the specified operation is not allowed in the current state")
- << error_info("GL_INVALID_OPERATION")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_invalid_operation()
+ << msg_info("the specified operation is not allowed in the current state")
+ << error_info("GL_INVALID_OPERATION")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
case GL_STACK_OVERFLOW :
- CASPAR_THROW_EXCEPTION(ogl_stack_overflow()
- << msg_info("this command would cause a stack overflow")
- << error_info("GL_STACK_OVERFLOW")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_stack_overflow()
+ << msg_info("this command would cause a stack overflow")
+ << error_info("GL_STACK_OVERFLOW")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
case GL_STACK_UNDERFLOW :
- CASPAR_THROW_EXCEPTION(ogl_stack_underflow()
- << msg_info("this command would cause a stack underflow")
- << error_info("GL_STACK_UNDERFLOW")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_stack_underflow()
+ << msg_info("this command would cause a stack underflow")
+ << error_info("GL_STACK_UNDERFLOW")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
case GL_OUT_OF_MEMORY :
- CASPAR_THROW_EXCEPTION(ogl_out_of_memory()
- << msg_info("there is not enough memory left to execute the command")
- << error_info("GL_OUT_OF_MEMORY")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_out_of_memory()
+ << msg_info("there is not enough memory left to execute the command")
+ << error_info("GL_OUT_OF_MEMORY")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
case GL_INVALID_FRAMEBUFFER_OPERATION_EXT :
- CASPAR_THROW_EXCEPTION(ogl_stack_underflow()
- << msg_info("the object bound to FRAMEBUFFER_BINDING_EXT is not \"framebuffer complete\"")
- << error_info("GL_INVALID_FRAMEBUFFER_OPERATION_EXT")
- << line_info(line)
- << source_info(file));
+ ::boost::exception_detail::throw_exception_(
+ ogl_invalid_framebuffer_operation_ext()
+ << msg_info("the object bound to FRAMEBUFFER_BINDING_EXT is not \"framebuffer complete\"")
+ << error_info("GL_INVALID_FRAMEBUFFER_OPERATION_EXT")
+ << call_stack_info(caspar::get_call_stack())
+ << context_info(get_context()),
+ func, log::remove_source_prefix(file), line);
}
}
}
struct ogl_invalid_value : virtual ogl_exception{};
struct ogl_invalid_operation : virtual ogl_exception{};
struct ogl_stack_overflow : virtual ogl_exception{};
-struct ogl_stack_underflow : virtual ogl_exception{};
+struct ogl_stack_underflow : virtual ogl_exception{};
struct ogl_out_of_memory : virtual ogl_exception{};
struct ogl_invalid_framebuffer_operation_ext : virtual ogl_exception{};
-void SMFL_GLCheckError(const std::string& expr, const std::string& File, unsigned int Line);
+void SMFL_GLCheckError(const std::string& expr, const char* func, const char* file, unsigned int line);
//#ifdef _DEBUG
-
+
#define CASPAR_GL_EXPR_STR(expr) #expr
#define GL(expr) \
if(false){}else \
{ \
(expr); \
- caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__);\
+ caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FUNCTION__, __FILE__, __LINE__);\
}
// TODO: decltype version does not play well with gcc
[&]()\
{\
auto ret = (expr);\
- caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__);\
+ caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FUNCTION__, __FILE__, __LINE__);\
return ret;\
}()
/*#define GL2(expr) \
}
namespace internal{
-
+
void init()
-{
+{
boost::log::add_common_attributes();
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::wtext_ostream_backend> stream_sink_type;
print_child(level, indent + (elem.empty() ? L"" : elem + L"."), child.first, child.second);
}
+const char* remove_source_prefix(const char* file)
+{
+ auto found = boost::ifind_first(file, get_source_prefix().c_str());
+
+ if (found)
+ return found.end();
+ else
+ return file;
+}
+
}}
#include <memory>
namespace caspar { namespace log {
-
+
namespace internal{
void init();
std::wstring get_call_stack();
}
+const char* remove_source_prefix(const char* file);
+
template<typename T>
inline void replace_nonprintable(std::basic_string<T, std::char_traits<T>, std::allocator<T>>& str, T with)
{
std::locale loc;
std::replace_if(str.begin(), str.end(), [&](T c)->bool {
- return
- (!std::isprint(c, loc)
- && c != '\r'
+ return
+ (!std::isprint(c, loc)
+ && c != '\r'
&& c != '\n')
|| c > static_cast<T>(127);
}, with);
const boost::property_tree::wptree& tree);
}}
-
}
}
+const std::string& get_source_prefix()
+{
+ static const std::string SOURCE_PREFIX;
+ return SOURCE_PREFIX;
+}
+
}
+
namespace caspar {
std::wstring get_call_stack();
+const std::string& get_source_prefix();
}
#include "../../compiler/vs/StackWalker.h"
+#include <boost/algorithm/string/replace.hpp>
+
#include <utility>
#include <tbb/enumerable_thread_specific.h>
+#include <boost/algorithm/string/find.hpp>
namespace caspar {
{
std::string str_ = "\n";
public:
- log_call_stack_walker() : StackWalker() {}
+ log_call_stack_walker()
+ : StackWalker()
+ {
+ }
std::string flush()
{
- return std::move(str_);
+ auto result = std::move(str_);
+
+ str_ = "\n";
+
+ return result;
}
protected:
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName) override
{
std::string str = szText;
- if(str.find("caspar::get_call_stack") == std::string::npos && str.find("StackWalker::ShowCallstack") == std::string::npos)
+ auto include_path = boost::find_first(str, "\\include\\");
+
+ if (include_path)
+ {
+ str.erase(str.begin(), include_path.end());
+ }
+
+ boost::ireplace_all(str, get_source_prefix(), "");
+
+ if (str.find("caspar::get_call_stack") == std::string::npos &&
+ str.find("StackWalker::ShowCallstack") == std::string::npos)
+ {
str_ += " " + std::move(str);
+ }
}
};
}
catch(...)
{
- return L"!!!";
+ return L"Bug in stacktrace code!!!";
}
}
+const std::string& get_source_prefix()
+{
+ static const std::string SOURCE_PREFIX = []
+ {
+ std::string result = CASPAR_SOURCE_PREFIX;
+
+ boost::replace_all(result, "/", "\\");
+ result += "\\";
+
+ return result;
+ }();
+
+ return SOURCE_PREFIX;
+}
+
}
#include "ffmpeg_error.h"
#include <common/utf.h>
+#include <common/log.h>
#pragma warning(disable: 4146)
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_DECODER_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_decoder_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_DEMUXER_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_demuxer_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_ENCODER_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_encoder_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_EOF:
::boost::exception_detail::throw_exception_(
averror_eof()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_EXIT:
::boost::exception_detail::throw_exception_(
averror_exit()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_FILTER_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_filter_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_MUXER_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_muxer_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_OPTION_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_option_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_PATCHWELCOME:
::boost::exception_detail::throw_exception_(
averror_patchwelcome()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_PROTOCOL_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_protocol_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVERROR_STREAM_NOT_FOUND:
::boost::exception_detail::throw_exception_(
averror_stream_not_found()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
case AVUNERROR(EINVAL):
::boost::exception_detail::throw_exception_(
averror_invalid_argument()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
default:
::boost::exception_detail::throw_exception_(
ffmpeg_error()
<< boost::errinfo_errno(AVUNERROR(ret))
<< call_stack_info(caspar::get_call_stack())
<< context_info(get_context()),
- local_func, file, line);
+ local_func, log::remove_source_prefix(file), line);
}
}