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
This commit is contained in:
Martin Hořeňovský 2017-03-06 21:51:22 +01:00
parent e95bf48445
commit 613e1466f9
4 changed files with 34 additions and 0 deletions

View File

@ -135,6 +135,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_debugger.h ${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_debugger.hpp ${HEADER_DIR}/internal/catch_debugger.hpp
${HEADER_DIR}/internal/catch_default_main.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_evaluate.hpp
${HEADER_DIR}/internal/catch_exception_translator_registry.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.hpp
${HEADER_DIR}/internal/catch_expression_lhs.hpp ${HEADER_DIR}/internal/catch_expression_lhs.hpp

View File

@ -10,6 +10,7 @@
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#include "catch_debugger.h" #include "catch_debugger.h"
#include "catch_errno_guard.hpp"
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
@ -72,6 +73,9 @@
// be strace, for example) in /proc/$PID/status, so just get it from // be strace, for example) in /proc/$PID/status, so just get it from
// there instead. // there instead.
bool isDebuggerActive(){ 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"); std::ifstream in("/proc/self/status");
for( std::string line; std::getline(in, line); ) { for( std::string line; std::getline(in, line); ) {
static const int PREFIX_LEN = 11; static const int PREFIX_LEN = 11;

View File

@ -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 <cerrno>
namespace Catch {
class ErrnoGuard {
public:
ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard() { errno = m_oldErrno; }
private:
int m_oldErrno;
};
}
#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED

View File

@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include "../internal/catch_interfaces_reporter.h" #include "../internal/catch_interfaces_reporter.h"
#include "../internal/catch_errno_guard.hpp"
#include <cstring> #include <cstring>
#include <cfloat> #include <cfloat>
@ -27,6 +28,9 @@ namespace Catch {
// + 1 for null terminator // + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize]; char buffer[maxDoubleSize];
// Save previous errno, to prevent sprintf from overwriting it
ErrnoGuard guard;
#ifdef _MSC_VER #ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration); sprintf_s(buffer, "%.3f", duration);
#else #else