未验证 提交 657a8c8f 编写于 作者: 石晓伟 提交者: GitHub

experimental feature: error status, test=develop (#35624)

上级 174535b1
...@@ -76,6 +76,7 @@ set(SHARED_INFERENCE_SRCS ...@@ -76,6 +76,7 @@ set(SHARED_INFERENCE_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/api/api.cc ${CMAKE_CURRENT_SOURCE_DIR}/api/api.cc
${CMAKE_CURRENT_SOURCE_DIR}/api/api_impl.cc ${CMAKE_CURRENT_SOURCE_DIR}/api/api_impl.cc
${CMAKE_CURRENT_SOURCE_DIR}/api/analysis_predictor.cc ${CMAKE_CURRENT_SOURCE_DIR}/api/analysis_predictor.cc
${CMAKE_CURRENT_SOURCE_DIR}/api/paddle_infer_contrib.cc
${CMAKE_CURRENT_SOURCE_DIR}/api/details/zero_copy_tensor.cc ${CMAKE_CURRENT_SOURCE_DIR}/api/details/zero_copy_tensor.cc
${CMAKE_CURRENT_SOURCE_DIR}/utils/io_utils.cc ${CMAKE_CURRENT_SOURCE_DIR}/utils/io_utils.cc
${PADDLE_CUSTOM_OP_SRCS}) ${PADDLE_CUSTOM_OP_SRCS})
......
...@@ -186,5 +186,44 @@ void TensorUtils::CopyTensorAsync(Tensor* p_dst, const Tensor& src, ...@@ -186,5 +186,44 @@ void TensorUtils::CopyTensorAsync(Tensor* p_dst, const Tensor& src,
CopyTensorImpl(p_dst, src, nullptr, cb, cb_params); CopyTensorImpl(p_dst, src, nullptr, cb, cb_params);
} }
struct Status::Impl {
int ec{0};
std::string msg;
};
Status::Status() noexcept : impl_(new Impl) {}
Status::Status(const Status& status) noexcept : impl_(new Impl) {
*impl_ = *status.impl_;
}
Status& Status::operator=(const Status& status) noexcept {
*impl_ = *status.impl_;
return *this;
}
Status::Status(std::exception_ptr e) noexcept : impl_(new Impl) {
constexpr int kDefaultError{-1};
impl_->ec = kDefaultError;
try {
std::rethrow_exception(e);
} catch (paddle::platform::EnforceNotMet& e) {
// Add one to the error code to make the number zero a non-error
// status code.
impl_->ec = e.code() + 1;
impl_->msg = e.what();
} catch (const std::exception& e) {
impl_->msg = e.what();
}
}
Status Status::OK() noexcept { return Status(); }
bool Status::ok() const noexcept { return impl_->ec == 0; }
Status::Code Status::code() const noexcept { return impl_->ec; }
const std::string& Status::error_message() const noexcept { return impl_->msg; }
bool Status::operator==(const Status& x) const noexcept {
return code() == x.code() && error_message() == x.error_message();
}
bool Status::operator!=(const Status& x) const noexcept {
return !(*this == x);
}
} // namespace contrib } // namespace contrib
} // namespace paddle_infer } // namespace paddle_infer
...@@ -36,5 +36,91 @@ class TensorUtils { ...@@ -36,5 +36,91 @@ class TensorUtils {
void* cb_params); void* cb_params);
}; };
/// \brief A status class, used to intercept exceptions and convert
/// them into a status number.
class Status {
public:
using Code = int;
struct Impl;
Status() noexcept;
explicit Status(std::exception_ptr e) noexcept;
Status(const Status&) noexcept;
Status& operator=(const Status&) noexcept;
Status& operator=(Status&&) = default;
Status(Status&&) = default;
///
/// \brief Construct a status which indicate ok.
///
/// \return A status which indicate ok.
///
static Status OK() noexcept;
///
/// \brief Determine whether the status is ok.
///
/// \return Whether the status is ok.
///
bool ok() const noexcept;
///
/// \brief Return the error code.
/// The meaning corresponds to the following.
///
/// CODE IMPLICATION
/// -1 UNKNOWN
/// 0 NORMAL
/// 1 LEGACY
/// 2 INVALID_ARGUMENT
/// 3 NOT_FOUND
/// 4 OUT_OF_RANGE
/// 5 ALREADY_EXISTS
/// 6 RESOURCE_EXHAUSTED
/// 7 PRECONDITION_NOT_MET
/// 8 PERMISSION_DENIED
/// 9 EXECUTION_TIMEOUT
/// 10 UNIMPLEMENTED
/// 11 UNAVAILABLE
/// 12 FATAL
/// 13 EXTERNAL
///
/// \return The error code.
///
Code code() const noexcept;
///
/// \brief Return the error message.
///
/// \return The error message.
///
const std::string& error_message() const noexcept;
bool operator==(const Status& x) const noexcept;
bool operator!=(const Status& x) const noexcept;
private:
std::shared_ptr<Impl> impl_;
};
///
/// \brief A wrapper used to provide exception safety.
///
/// \param func Wrapped function.
/// \param args Parameters of the wrapped function.
/// \return State result of calling function.
///
template <typename Func, typename... Args>
Status get_status(Func func, Args&&... args) noexcept(
noexcept(Status(std::declval<Status>()))) {
try {
func(std::forward<Args>(args)...);
} catch (...) {
return Status(std::current_exception());
}
return Status::OK();
}
} // namespace contrib } // namespace contrib
} // namespace paddle_infer } // namespace paddle_infer
...@@ -708,6 +708,8 @@ if(WITH_GPU) ...@@ -708,6 +708,8 @@ if(WITH_GPU)
set_tests_properties(paddle_infer_api_copy_tensor_tester PROPERTIES TIMEOUT 30) set_tests_properties(paddle_infer_api_copy_tensor_tester PROPERTIES TIMEOUT 30)
endif() endif()
cc_test(paddle_infer_api_errors_test SRCS paddle_infer_api_errors_tester.cc DEPS paddle_inference_api)
if("$ENV{CI_SKIP_CPP_TEST}" STREQUAL "ON") if("$ENV{CI_SKIP_CPP_TEST}" STREQUAL "ON")
return() return()
endif() endif()
......
// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// 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 "gflags/gflags.h"
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/fluid/inference/api/paddle_infer_contrib.h"
#include "paddle/fluid/platform/enforce.h"
namespace paddle_infer {
namespace contrib {
TEST(Status, ctor) { CHECK(Status::OK().ok()); }
struct FakeException {
void pd_exception(int a) const {
PADDLE_ENFORCE_NE(a, a,
paddle::platform::errors::InvalidArgument(
"This is a preset error message used to verify "
"whether the exception meets expectations: %d, %d.",
a, a));
}
[[noreturn]] void base_exception() const { throw std::exception(); }
void no_exception() const noexcept {}
};
TEST(Status, pd_exception) {
FakeException e;
Status status = get_status([&]() { e.pd_exception(1); });
CHECK(!status.ok());
CHECK(status == status);
CHECK(!(status != status));
CHECK_EQ(status.code(), paddle::platform::error::INVALID_ARGUMENT + 1);
LOG(INFO) << status.error_message();
}
TEST(Status, basic_exception) {
FakeException e;
Status status;
status = get_status([&]() { e.base_exception(); });
CHECK(!status.ok());
LOG(INFO) << status.error_message();
}
TEST(Status, no_exception) {
FakeException e;
Status status;
status = get_status([&]() { e.no_exception(); });
CHECK(status.ok());
}
TEST(Status, copy) {
Status status;
Status status_1(status);
status_1 = status;
}
} // namespace contrib
} // namespace paddle_infer
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册