From 613e1466f9ef7e068fd08327fd04cfd25df4fb3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 6 Mar 2017 21:51:22 +0100 Subject: [PATCH] Save errno before using sprintf, ifstream. std::ifstream in libstdc++ contains a bug, where it sets errno to zero. To work around it, we manually save the errno before using std::ifstream in debugger check, and reset it after we are done. We also preventively save errno before using sprintf. Fixes #835 --- CMakeLists.txt | 1 + include/internal/catch_debugger.hpp | 4 ++++ include/internal/catch_errno_guard.hpp | 25 ++++++++++++++++++++++ include/reporters/catch_reporter_bases.hpp | 4 ++++ 4 files changed, 34 insertions(+) create mode 100644 include/internal/catch_errno_guard.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 67f4058f..159fcce9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_debugger.h ${HEADER_DIR}/internal/catch_debugger.hpp ${HEADER_DIR}/internal/catch_default_main.hpp + ${HEADER_DIR}/internal/catch_errno_guard.hpp ${HEADER_DIR}/internal/catch_evaluate.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.hpp ${HEADER_DIR}/internal/catch_expression_lhs.hpp diff --git a/include/internal/catch_debugger.hpp b/include/internal/catch_debugger.hpp index 47daf8ad..00017d16 100644 --- a/include/internal/catch_debugger.hpp +++ b/include/internal/catch_debugger.hpp @@ -10,6 +10,7 @@ #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #include "catch_debugger.h" +#include "catch_errno_guard.hpp" #ifdef CATCH_PLATFORM_MAC @@ -72,6 +73,9 @@ // be strace, for example) in /proc/$PID/status, so just get it from // there instead. bool isDebuggerActive(){ + // Libstdc++ has a bug, where std::ifstream sets errno to 0 + // This way our users can properly assert over errno values + ErrnoGuard guard; std::ifstream in("/proc/self/status"); for( std::string line; std::getline(in, line); ) { static const int PREFIX_LEN = 11; diff --git a/include/internal/catch_errno_guard.hpp b/include/internal/catch_errno_guard.hpp new file mode 100644 index 00000000..48794b08 --- /dev/null +++ b/include/internal/catch_errno_guard.hpp @@ -0,0 +1,25 @@ +/* + * Created by Martin on 06/03/2017. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED + +#include + + +namespace Catch { + + class ErrnoGuard { + public: + ErrnoGuard():m_oldErrno(errno){} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + +} + +#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 8fc8554b..aca5f355 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #include "../internal/catch_interfaces_reporter.h" +#include "../internal/catch_errno_guard.hpp" #include #include @@ -27,6 +28,9 @@ namespace Catch { // + 1 for null terminator const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; char buffer[maxDoubleSize]; + + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; #ifdef _MSC_VER sprintf_s(buffer, "%.3f", duration); #else