Commit 09634ef5 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

FOLLY_SAFE_PCHECK

Summary: [Folly] `FOLLY_SAFE_PCHECK`, for reporting errors from C standard library functions which may set errno from within code which must be reentrant.

Reviewed By: nbronson

Differential Revision: D19222785

fbshipit-source-id: 532ccee39c9d180b9b17edbd31517c09024539d7
parent 1cd1bfb6
This diff is collapsed.
...@@ -16,23 +16,28 @@ ...@@ -16,23 +16,28 @@
#pragma once #pragma once
#include <cerrno>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/Preprocessor.h> #include <folly/Preprocessor.h>
#define FOLLY_SAFE_CHECK_IMPL(expr, expr_s, msg, error) \
((expr) ? static_cast<void>(0) \
: ::folly::detail::assertionFailure( \
FB_STRINGIZE(expr_s), \
(msg), \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
error))
/** /**
* Verify that the expression is true. If not, prints an error message * Verify that the expression is true. If not, prints an error message
* (containing msg) to stderr and abort()s. Just like CHECK(), but only * (containing msg) to stderr and abort()s. Just like CHECK(), but only
* logs to stderr and only does async-signal-safe calls. * logs to stderr and only does async-signal-safe calls.
*/ */
#define FOLLY_SAFE_CHECK_IMPL(expr, expr_s, msg) \ #define FOLLY_SAFE_CHECK(expr, msg) \
((expr) ? static_cast<void>(0) \ FOLLY_SAFE_CHECK_IMPL((expr), (expr), (msg), 0)
: ::folly::detail::assertionFailure( \
FB_STRINGIZE(expr_s), \
(msg), \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__))
#define FOLLY_SAFE_CHECK(expr, msg) FOLLY_SAFE_CHECK_IMPL((expr), (expr), (msg))
/** /**
* In debug mode, verify that the expression is true. Otherwise, do nothing * In debug mode, verify that the expression is true. Otherwise, do nothing
...@@ -40,7 +45,13 @@ ...@@ -40,7 +45,13 @@
* only does async-signal-safe calls. * only does async-signal-safe calls.
*/ */
#define FOLLY_SAFE_DCHECK(expr, msg) \ #define FOLLY_SAFE_DCHECK(expr, msg) \
FOLLY_SAFE_CHECK_IMPL(!::folly::kIsDebug || (expr), (expr), (msg)) FOLLY_SAFE_CHECK_IMPL(!::folly::kIsDebug || (expr), (expr), (msg), 0)
/**
* Like FOLLY_SAFE_CHECK, but also prints errno.
*/
#define FOLLY_SAFE_PCHECK(expr, msg) \
FOLLY_SAFE_CHECK_IMPL((expr), (expr), (msg), errno)
namespace folly { namespace folly {
namespace detail { namespace detail {
...@@ -50,6 +61,7 @@ namespace detail { ...@@ -50,6 +61,7 @@ namespace detail {
const char* msg, const char* msg,
const char* file, const char* file,
unsigned int line, unsigned int line,
const char* function); const char* function,
int error);
} // namespace detail } // namespace detail
} // namespace folly } // namespace folly
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <folly/Benchmark.h> #include <folly/Benchmark.h>
#include <folly/Conv.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
// clang-format off // clang-format off
...@@ -36,3 +37,12 @@ TEST(SafeAssert, AssertionFailure) { ...@@ -36,3 +37,12 @@ TEST(SafeAssert, AssertionFailure) {
EXPECT_DEATH(fail(), "Assertion failure: 0 \\+ 0"); EXPECT_DEATH(fail(), "Assertion failure: 0 \\+ 0");
EXPECT_DEATH(fail(), "Message: hello"); EXPECT_DEATH(fail(), "Message: hello");
} }
TEST(SafeAssert, AssertionFailureErrno) {
EXPECT_DEATH(
FOLLY_SAFE_PCHECK((errno = EINVAL) && false, "hello"),
folly::to<std::string>("Error: ", EINVAL, " \\(EINVAL\\)"));
EXPECT_DEATH(
FOLLY_SAFE_PCHECK((errno = 999) && false, "hello"),
folly::to<std::string>("Error: 999 \\(<unknown>\\)"));
}
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