From 04cd54b79d84e63431230ecee106aede02151521 Mon Sep 17 00:00:00 2001 From: Helge Norberg Date: Tue, 22 Nov 2016 20:39:52 +0100 Subject: [PATCH] [logging] Suppress the logging of full path names in stack traces so that only the relative path within the source tree is visible. --- CHANGELOG | 2 + CMakeLists.txt | 1 + common/assert.h | 4 +- common/except.h | 6 +-- common/gl/gl_check.cpp | 88 ++++++++++++++++++------------- common/gl/gl_check.h | 10 ++-- common/log.cpp | 14 ++++- common/log.h | 11 ++-- common/os/linux/stack_trace.cpp | 7 +++ common/os/stack_trace.h | 1 + common/os/windows/stack_trace.cpp | 45 ++++++++++++++-- modules/ffmpeg/ffmpeg_error.cpp | 29 +++++----- 12 files changed, 146 insertions(+), 72 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 86a28aee5..5a4902520 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,8 @@ General creatable/writable. o Added backwards compatibility (with deprecation warning) for using thumbnails-path instead of thumbnail-path in casparcg.config. + o Suppress the logging of full path names in stack traces so that only the + relative path within the source tree is visible. AMCP ---- diff --git a/CMakeLists.txt b/CMakeLists.txt index e4276b470..d2e81f8d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ add_definitions( -D_UNICODE ) 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") diff --git a/common/assert.h b/common/assert.h index 79dd587cf..b88192648 100644 --- a/common/assert.h +++ b/common/assert.h @@ -34,7 +34,7 @@ #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); @@ -46,4 +46,4 @@ #define CASPAR_ASSERT(expr) CASPAR_VERIFY(expr) #else #define CASPAR_ASSERT(expr) -#endif \ No newline at end of file +#endif diff --git a/common/except.h b/common/except.h index f4319f6d3..a830a9300 100644 --- a/common/except.h +++ b/common/except.h @@ -24,6 +24,7 @@ #include "utf.h" #include "os/stack_trace.h" +#include "log.h" #include #include @@ -64,7 +65,7 @@ inline context_info_t context_info(const T& str) {return context_info_t(u8(str typedef boost::error_info line_info; typedef boost::error_info 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 @@ -125,9 +126,8 @@ private: #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); } - diff --git a/common/gl/gl_check.cpp b/common/gl/gl_check.cpp index 2ff4642d8..72b123061 100644 --- a/common/gl/gl_check.cpp +++ b/common/gl/gl_check.cpp @@ -30,9 +30,9 @@ #include -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; @@ -49,53 +49,67 @@ void SMFL_GLCheckError(const std::string&, const std::string& file, unsigned int 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); } } } diff --git a/common/gl/gl_check.h b/common/gl/gl_check.h index 2ba7fa003..f6ceb8525 100644 --- a/common/gl/gl_check.h +++ b/common/gl/gl_check.h @@ -33,21 +33,21 @@ struct ogl_invalid_enum : virtual ogl_exception{}; 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 @@ -55,7 +55,7 @@ void SMFL_GLCheckError(const std::string& expr, const std::string& File, unsigne [&]()\ {\ 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) \ diff --git a/common/log.cpp b/common/log.cpp index 31a345776..1ad6a38f7 100644 --- a/common/log.cpp +++ b/common/log.cpp @@ -141,9 +141,9 @@ void my_formatter(bool print_all_characters, const boost::log::record_view& rec, } namespace internal{ - + void init() -{ +{ boost::log::add_common_attributes(); typedef boost::log::sinks::asynchronous_sink stream_sink_type; @@ -323,4 +323,14 @@ void print_child( 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; +} + }} diff --git a/common/log.h b/common/log.h index 4cc983e45..860c1a646 100644 --- a/common/log.h +++ b/common/log.h @@ -39,20 +39,22 @@ #include namespace caspar { namespace log { - + namespace internal{ void init(); std::wstring get_call_stack(); } +const char* remove_source_prefix(const char* file); + template inline void replace_nonprintable(std::basic_string, std::allocator>& 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(127); }, with); @@ -119,4 +121,3 @@ void print_child( const boost::property_tree::wptree& tree); }} - diff --git a/common/os/linux/stack_trace.cpp b/common/os/linux/stack_trace.cpp index c2369e2c8..1419a02fb 100644 --- a/common/os/linux/stack_trace.cpp +++ b/common/os/linux/stack_trace.cpp @@ -102,4 +102,11 @@ std::wstring get_call_stack() } } +const std::string& get_source_prefix() +{ + static const std::string SOURCE_PREFIX; + return SOURCE_PREFIX; +} + } + diff --git a/common/os/stack_trace.h b/common/os/stack_trace.h index 2062372bc..efc1a6d35 100644 --- a/common/os/stack_trace.h +++ b/common/os/stack_trace.h @@ -26,5 +26,6 @@ namespace caspar { std::wstring get_call_stack(); +const std::string& get_source_prefix(); } diff --git a/common/os/windows/stack_trace.cpp b/common/os/windows/stack_trace.cpp index ff5dc28bf..0b361e732 100644 --- a/common/os/windows/stack_trace.cpp +++ b/common/os/windows/stack_trace.cpp @@ -26,9 +26,12 @@ #include "../../compiler/vs/StackWalker.h" +#include + #include #include +#include namespace caspar { @@ -38,11 +41,18 @@ std::wstring get_call_stack() { 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 @@ -58,8 +68,20 @@ std::wstring get_call_stack() { 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); + } } }; @@ -72,8 +94,23 @@ std::wstring get_call_stack() } 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; +} + } diff --git a/modules/ffmpeg/ffmpeg_error.cpp b/modules/ffmpeg/ffmpeg_error.cpp index a69583f17..89b7dc70b 100644 --- a/modules/ffmpeg/ffmpeg_error.cpp +++ b/modules/ffmpeg/ffmpeg_error.cpp @@ -23,6 +23,7 @@ #include "ffmpeg_error.h" #include +#include #pragma warning(disable: 4146) @@ -58,7 +59,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -68,7 +69,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -78,7 +79,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -88,7 +89,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -98,7 +99,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -108,7 +109,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -118,7 +119,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -128,7 +129,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -138,7 +139,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -148,7 +149,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -158,7 +159,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -168,7 +169,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -178,7 +179,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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() @@ -188,7 +189,7 @@ void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const << 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); } } -- 2.39.2