Commit 52286a8b authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot 3

Add a utility for disabling some CRT assertions in debug mode

Summary:
See the comment on `msvcReturnInvalidParams` for more info on the issue.
This also adds a use of it to TestUtilTest.

Reviewed By: yfeldblum

Differential Revision: D3691526

fbshipit-source-id: f0f596e9b4c830e1d31de01926162636757329e8
parent 60136d87
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <folly/portability/Fcntl.h> #include <folly/portability/Fcntl.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#ifdef _WIN32
#include <crtdbg.h>
#endif
namespace folly { namespace folly {
namespace test { namespace test {
...@@ -128,6 +132,32 @@ ChangeToTempDir::~ChangeToTempDir() { ...@@ -128,6 +132,32 @@ ChangeToTempDir::~ChangeToTempDir() {
namespace detail { namespace detail {
SavedState disableInvalidParameters() {
#ifdef _WIN32
SavedState ret;
ret.previousThreadLocalHandler = _set_thread_local_invalid_parameter_handler(
[](const wchar_t*,
const wchar_t*,
const wchar_t*,
unsigned int,
uintptr_t) {});
ret.previousCrtReportMode = _CrtSetReportMode(_CRT_ASSERT, 0);
return ret;
#else
return SavedState();
#endif
}
#ifdef _WIN32
void enableInvalidParameters(SavedState state) {
_set_thread_local_invalid_parameter_handler(
(_invalid_parameter_handler)state.previousThreadLocalHandler);
_CrtSetReportMode(_CRT_ASSERT, state.previousCrtReportMode);
}
#else
void enableInvalidParameters(SavedState) {}
#endif
bool hasPCREPatternMatch(StringPiece pattern, StringPiece target) { bool hasPCREPatternMatch(StringPiece pattern, StringPiece target) {
return boost::regex_match( return boost::regex_match(
target.begin(), target.begin(),
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <folly/Range.h> #include <folly/Range.h>
#include <folly/ScopeGuard.h>
#include <folly/experimental/io/FsUtil.h> #include <folly/experimental/io/FsUtil.h>
namespace folly { namespace folly {
...@@ -118,6 +119,33 @@ private: ...@@ -118,6 +119,33 @@ private:
TemporaryDirectory dir_; TemporaryDirectory dir_;
}; };
namespace detail {
struct SavedState {
void* previousThreadLocalHandler;
int previousCrtReportMode;
};
SavedState disableInvalidParameters();
void enableInvalidParameters(SavedState state);
}
// Ok, so fun fact: The CRT on windows will actually abort
// on certain failed parameter validation checks in debug
// mode rather than simply returning -1 as it does in release
// mode. We can however, ensure consistent behavior by
// registering our own thread-local invalid parameter handler
// for the duration of the call, and just have that handler
// immediately return. We also have to disable CRT asertion
// alerts for the duration of the call, otherwise we get
// the abort-retry-ignore window.
template <typename Func>
auto msvcSuppressAbortOnInvalidParams(Func func) -> decltype(func()) {
auto savedState = detail::disableInvalidParameters();
SCOPE_EXIT {
detail::enableInvalidParameters(savedState);
};
return func();
}
/** /**
* Easy PCRE regex matching. Note that pattern must match the ENTIRE target, * Easy PCRE regex matching. Note that pattern must match the ENTIRE target,
* so use .* at the start and end of the pattern, as appropriate. See * so use .* at the start and end of the pattern, as appropriate. See
......
...@@ -45,6 +45,7 @@ TEST(TemporaryFile, Simple) { ...@@ -45,6 +45,7 @@ TEST(TemporaryFile, Simple) {
EXPECT_EQ(1, r); EXPECT_EQ(1, r);
} }
msvcSuppressAbortOnInvalidParams([&] {
// The file must have been closed. This assumes that no other thread // The file must have been closed. This assumes that no other thread
// has opened another file in the meanwhile, which is a sane assumption // has opened another file in the meanwhile, which is a sane assumption
// to make in this test. // to make in this test.
...@@ -52,6 +53,7 @@ TEST(TemporaryFile, Simple) { ...@@ -52,6 +53,7 @@ TEST(TemporaryFile, Simple) {
int savedErrno = errno; int savedErrno = errno;
EXPECT_EQ(-1, r); EXPECT_EQ(-1, r);
EXPECT_EQ(EBADF, savedErrno); EXPECT_EQ(EBADF, savedErrno);
});
} }
TEST(TemporaryFile, Prefix) { TEST(TemporaryFile, Prefix) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment