Commit 20272b4e authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

add makeSystemError*() helper functions

Summary:
Add makeSystemError() helper functions that are similar to the existing
throwSystemError() functions but just return the exception rather than throwing
it.  This is helpful for callers using folly::Expected or folly::Future, where
they need to return an exception type rather than throwing it.

This also includes comments about the fact that this code is using the wrong
error category.  The C++ standard indicates that std::generic_category() for
POSIX errno values.  I am not fixing this as part of this diff, since this
change has the potential to break existing users, and would need a fair amount
of testing first.

Reviewed By: yfeldblum

Differential Revision: D6456771

fbshipit-source-id: 4724b51b8d4a7f513ae70ea1b0c4f0516cfc205f
parent ad993b99
......@@ -35,15 +35,40 @@ namespace folly {
//
// The *Explicit functions take an explicit value for errno.
inline std::system_error makeSystemErrorExplicit(int err, const char* msg) {
// TODO: The C++ standard indicates that std::generic_category() should be
// used for POSIX errno codes.
//
// We should ideally change this to use std::generic_category() instead of
// std::system_category(). However, undertaking this change will require
// updating existing call sites that currently catch exceptions thrown by
// this code and currently expect std::system_category.
return std::system_error(err, std::system_category(), msg);
}
template <class... Args>
std::system_error makeSystemErrorExplicit(int err, Args&&... args) {
return makeSystemErrorExplicit(
err, to<fbstring>(std::forward<Args>(args)...).c_str());
}
inline std::system_error makeSystemError(const char* msg) {
return makeSystemErrorExplicit(errno, msg);
}
template <class... Args>
std::system_error makeSystemError(Args&&... args) {
return makeSystemErrorExplicit(errno, std::forward<Args>(args)...);
}
// Helper to throw std::system_error
[[noreturn]] inline void throwSystemErrorExplicit(int err, const char* msg) {
throw std::system_error(err, std::system_category(), msg);
throw makeSystemErrorExplicit(err, msg);
}
template <class... Args>
[[noreturn]] void throwSystemErrorExplicit(int err, Args&&... args) {
throwSystemErrorExplicit(
err, to<fbstring>(std::forward<Args>(args)...).c_str());
throw makeSystemErrorExplicit(err, std::forward<Args>(args)...);
}
// Helper to throw std::system_error from errno and components of a string
......
......@@ -90,5 +90,34 @@ TEST(ExceptionTest, Simple) {
EIO, "hello world");
}
TEST(ExceptionTest, makeSystemError) {
errno = ENOENT;
auto ex = makeSystemErrorExplicit(EDEADLK, "stuck");
EXPECT_EQ(EDEADLK, ex.code().value());
EXPECT_EQ(std::system_category(), ex.code().category());
EXPECT_TRUE(StringPiece{ex.what()}.contains("stuck"))
<< "what() string missing input message: " << ex.what();
ex = makeSystemErrorExplicit(EDOM, 300, " is bigger than max=", 255);
EXPECT_EQ(EDOM, ex.code().value());
EXPECT_EQ(std::system_category(), ex.code().category());
EXPECT_TRUE(StringPiece{ex.what()}.contains("300 is bigger than max=255"))
<< "what() string missing input message: " << ex.what();
errno = EINVAL;
ex = makeSystemError("bad argument ", 1234, ": bogus");
EXPECT_EQ(EINVAL, ex.code().value());
EXPECT_EQ(std::system_category(), ex.code().category());
EXPECT_TRUE(StringPiece{ex.what()}.contains("bad argument 1234: bogus"))
<< "what() string missing input message: " << ex.what();
errno = 0;
ex = makeSystemError("unexpected success");
EXPECT_EQ(0, ex.code().value());
EXPECT_EQ(std::system_category(), ex.code().category());
EXPECT_TRUE(StringPiece{ex.what()}.contains("unexpected success"))
<< "what() string missing input message: " << ex.what();
}
} // namespace test
} // namespace folly
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