From 25b8374ac42519da50960984b541a6740f5d851a Mon Sep 17 00:00:00 2001 From: Tudor Bosman Date: Wed, 27 Nov 2013 08:54:52 -0800 Subject: [PATCH] SafeAssert: async-signal-safe CHECK, DCHECK Summary: To be used from the (new) fatal signal handler. Test Plan: test added Reviewed By: lucian@fb.com FB internal diff: D1076168 @override-unit-failures --- folly/SafeAssert.cpp | 50 +++++++++++++++++++++++++++++++++ folly/SafeAssert.h | 53 +++++++++++++++++++++++++++++++++++ folly/test/SafeAssertTest.cpp | 38 +++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 folly/SafeAssert.cpp create mode 100644 folly/SafeAssert.h create mode 100644 folly/test/SafeAssertTest.cpp diff --git a/folly/SafeAssert.cpp b/folly/SafeAssert.cpp new file mode 100644 index 00000000..e9faca75 --- /dev/null +++ b/folly/SafeAssert.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "folly/SafeAssert.h" + +#include "folly/Conv.h" +#include "folly/FileUtil.h" + +namespace folly { namespace detail { + +namespace { +void writeStderr(const char* s) { + writeFull(STDERR_FILENO, s, strlen(s)); +} +} // namespace + +void assertionFailure(const char* expr, const char* msg, const char* file, + unsigned int line, const char* function) { + writeStderr("\n\nAssertion failure: "); + writeStderr(expr); + writeStderr("\nMessage: "); + writeStderr(msg); + writeStderr("\nFile: "); + writeStderr(file); + writeStderr("\nLine: "); + char buf[20]; + uint32_t n = uint64ToBufferUnsafe(line, buf); + writeFull(STDERR_FILENO, buf, n); + writeStderr("\nFunction: "); + writeStderr(function); + writeStderr("\n"); + fsyncNoInt(STDERR_FILENO); + abort(); +} + +}} // namespaces + diff --git a/folly/SafeAssert.h b/folly/SafeAssert.h new file mode 100644 index 00000000..5fbca62f --- /dev/null +++ b/folly/SafeAssert.h @@ -0,0 +1,53 @@ +/* + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOLLY_SAFEASSERT_H_ +#define FOLLY_SAFEASSERT_H_ + +#include "folly/Portability.h" +#include "folly/Preprocessor.h" + +/** + * Verify that the expression is true. If not, prints an error message + * (containing msg) to stderr and abort()s. Just like CHECK(), but only + * logs to stderr and only does async-signal-safe calls. + */ +#define FOLLY_SAFE_CHECK(expr, msg) \ + ((expr) ? static_cast(0) : \ + ::folly::detail::assertionFailure( \ + FB_STRINGIZE(expr), (msg), __FILE__, __LINE__, __PRETTY_FUNCTION__)) + +/** + * In debug mode, verify that the expression is true. Otherwise, do nothing + * (do not even evaluate expr). Just like assert() or DCHECK(), but only + * logs to stderr and only does async-signal-safe calls. + */ +#ifdef NDEBUG +#define FOLLY_SAFE_DCHECK(expr, msg) (static_cast(0)) +#else +#define FOLLY_SAFE_DCHECK FOLLY_SAFE_CHECK +#endif + +namespace folly { namespace detail { + +void assertionFailure(const char* expr, const char* msg, const char* file, + unsigned int line, const char* function) + FOLLY_NORETURN; + +}} // namespace folly + +#endif /* FOLLY_SAFEASSERT_H_ */ + diff --git a/folly/test/SafeAssertTest.cpp b/folly/test/SafeAssertTest.cpp new file mode 100644 index 00000000..f5d51def --- /dev/null +++ b/folly/test/SafeAssertTest.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "folly/SafeAssert.h" + +#include +#include + +#include "folly/Benchmark.h" + +using namespace folly; + +void fail() { + FOLLY_SAFE_CHECK(0, "hello"); +} + +void succeed() { + FOLLY_SAFE_CHECK(1, "world"); +} + +TEST(SafeAssert, AssertionFailure) { + succeed(); + EXPECT_DEATH(fail(), ".*Assertion failure:.*hello.*"); +} + -- 2.34.1