diff options
Diffstat (limited to 'grpc/src/core/lib/iomgr/error.h')
-rw-r--r-- | grpc/src/core/lib/iomgr/error.h | 325 |
1 files changed, 218 insertions, 107 deletions
diff --git a/grpc/src/core/lib/iomgr/error.h b/grpc/src/core/lib/iomgr/error.h index ac3ff876..aecd1e90 100644 --- a/grpc/src/core/lib/iomgr/error.h +++ b/grpc/src/core/lib/iomgr/error.h @@ -30,50 +30,70 @@ #include <grpc/support/time.h> #include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/status_helper.h" + +#include "absl/status/status.h" /// Opaque representation of an error. /// See https://github.com/grpc/grpc/blob/master/doc/core/grpc-error.md for a /// full write up of this object. +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + +typedef absl::Status grpc_error_handle; + +#else // GRPC_ERROR_IS_ABSEIL_STATUS + typedef struct grpc_error grpc_error; +typedef grpc_error* grpc_error_handle; -extern grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount; +#endif // GRPC_ERROR_IS_ABSEIL_STATUS typedef enum { /// 'errno' from the operating system - GRPC_ERROR_INT_ERRNO, + GRPC_ERROR_INT_ERRNO = + static_cast<int>(grpc_core::StatusIntProperty::kErrorNo), /// __LINE__ from the call site creating the error - GRPC_ERROR_INT_FILE_LINE, + GRPC_ERROR_INT_FILE_LINE = + static_cast<int>(grpc_core::StatusIntProperty::kFileLine), /// stream identifier: for errors that are associated with an individual /// wire stream - GRPC_ERROR_INT_STREAM_ID, + GRPC_ERROR_INT_STREAM_ID = + static_cast<int>(grpc_core::StatusIntProperty::kStreamId), /// grpc status code representing this error - GRPC_ERROR_INT_GRPC_STATUS, + GRPC_ERROR_INT_GRPC_STATUS = + static_cast<int>(grpc_core::StatusIntProperty::kRpcStatus), /// offset into some binary blob (usually represented by /// GRPC_ERROR_STR_RAW_BYTES) where the error occurred - GRPC_ERROR_INT_OFFSET, + GRPC_ERROR_INT_OFFSET = + static_cast<int>(grpc_core::StatusIntProperty::kOffset), /// context sensitive index associated with the error - GRPC_ERROR_INT_INDEX, + GRPC_ERROR_INT_INDEX = static_cast<int>(grpc_core::StatusIntProperty::kIndex), /// context sensitive size associated with the error - GRPC_ERROR_INT_SIZE, + GRPC_ERROR_INT_SIZE = static_cast<int>(grpc_core::StatusIntProperty::kSize), /// http2 error code associated with the error (see the HTTP2 RFC) - GRPC_ERROR_INT_HTTP2_ERROR, + GRPC_ERROR_INT_HTTP2_ERROR = + static_cast<int>(grpc_core::StatusIntProperty::kHttp2Error), /// TSI status code associated with the error - GRPC_ERROR_INT_TSI_CODE, - /// grpc_security_status associated with the error - GRPC_ERROR_INT_SECURITY_STATUS, + GRPC_ERROR_INT_TSI_CODE = + static_cast<int>(grpc_core::StatusIntProperty::kTsiCode), /// WSAGetLastError() reported when this error occurred - GRPC_ERROR_INT_WSA_ERROR, + GRPC_ERROR_INT_WSA_ERROR = + static_cast<int>(grpc_core::StatusIntProperty::kWsaError), /// File descriptor associated with this error - GRPC_ERROR_INT_FD, + GRPC_ERROR_INT_FD = static_cast<int>(grpc_core::StatusIntProperty::kFd), /// HTTP status (i.e. 404) - GRPC_ERROR_INT_HTTP_STATUS, - /// context sensitive limit associated with the error - GRPC_ERROR_INT_LIMIT, + GRPC_ERROR_INT_HTTP_STATUS = + static_cast<int>(grpc_core::StatusIntProperty::kHttpStatus), /// chttp2: did the error occur while a write was in progress - GRPC_ERROR_INT_OCCURRED_DURING_WRITE, + GRPC_ERROR_INT_OCCURRED_DURING_WRITE = + static_cast<int>(grpc_core::StatusIntProperty::kOccurredDuringWrite), /// channel connectivity state associated with the error - GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, + GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE = + static_cast<int>(grpc_core::StatusIntProperty::ChannelConnectivityState), + /// LB policy drop + GRPC_ERROR_INT_LB_POLICY_DROP = + static_cast<int>(grpc_core::StatusIntProperty::kLbPolicyDrop), /// Must always be last GRPC_ERROR_INT_MAX, @@ -81,29 +101,35 @@ typedef enum { typedef enum { /// top-level textual description of this error - GRPC_ERROR_STR_DESCRIPTION, + GRPC_ERROR_STR_DESCRIPTION = + static_cast<int>(grpc_core::StatusStrProperty::kDescription), /// source file in which this error occurred - GRPC_ERROR_STR_FILE, + GRPC_ERROR_STR_FILE = static_cast<int>(grpc_core::StatusStrProperty::kFile), /// operating system description of this error - GRPC_ERROR_STR_OS_ERROR, + GRPC_ERROR_STR_OS_ERROR = + static_cast<int>(grpc_core::StatusStrProperty::kOsError), /// syscall that generated this error - GRPC_ERROR_STR_SYSCALL, + GRPC_ERROR_STR_SYSCALL = + static_cast<int>(grpc_core::StatusStrProperty::kSyscall), /// peer that we were trying to communicate when this error occurred - GRPC_ERROR_STR_TARGET_ADDRESS, + GRPC_ERROR_STR_TARGET_ADDRESS = + static_cast<int>(grpc_core::StatusStrProperty::kTargetAddress), /// grpc status message associated with this error - GRPC_ERROR_STR_GRPC_MESSAGE, + GRPC_ERROR_STR_GRPC_MESSAGE = + static_cast<int>(grpc_core::StatusStrProperty::kGrpcMessage), /// hex dump (or similar) with the data that generated this error - GRPC_ERROR_STR_RAW_BYTES, + GRPC_ERROR_STR_RAW_BYTES = + static_cast<int>(grpc_core::StatusStrProperty::kRawBytes), /// tsi error string associated with this error - GRPC_ERROR_STR_TSI_ERROR, + GRPC_ERROR_STR_TSI_ERROR = + static_cast<int>(grpc_core::StatusStrProperty::kTsiError), /// filename that we were trying to read/write when this error occurred - GRPC_ERROR_STR_FILENAME, - /// which data was queued for writing when the error occurred - GRPC_ERROR_STR_QUEUED_BUFFERS, + GRPC_ERROR_STR_FILENAME = + static_cast<int>(grpc_core::StatusStrProperty::kFilename), /// key associated with the error - GRPC_ERROR_STR_KEY, + GRPC_ERROR_STR_KEY = static_cast<int>(grpc_core::StatusStrProperty::kKey), /// value associated with the error - GRPC_ERROR_STR_VALUE, + GRPC_ERROR_STR_VALUE = static_cast<int>(grpc_core::StatusStrProperty::kValue), /// Must always be last GRPC_ERROR_STR_MAX, @@ -117,32 +143,135 @@ typedef enum { GRPC_ERROR_TIME_MAX, } grpc_error_times; +// DEPRECATED: Use grpc_error_std_string instead +const char* grpc_error_string(grpc_error_handle error); +std::string grpc_error_std_string(grpc_error_handle error); + +// debug only toggles that allow for a sanity to check that ensures we will +// never create any errors in the per-RPC hotpath. +void grpc_disable_error_creation(); +void grpc_enable_error_creation(); + +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + +#define GRPC_ERROR_NONE absl::OkStatus() +#define GRPC_ERROR_OOM absl::Status(absl::ResourceExhaustedError) +#define GRPC_ERROR_CANCELLED absl::CancelledError() + +#define GRPC_ERROR_REF(err) (err) +#define GRPC_ERROR_UNREF(err) + +#define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc) \ + StatusCreate(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {}) +#define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc) \ + StatusCreate(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {}) +#define GRPC_ERROR_CREATE_FROM_STRING_VIEW(desc) \ + StatusCreate(ababsl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {}) + +absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg, + const grpc_core::DebugLocation& location, + size_t children_count, + absl::Status* children) GRPC_MUST_USE_RESULT; + +// Create an error that references some other errors. This function adds a +// reference to each error in errs - it does not consume an existing reference +#define GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(desc, errs, count) \ + grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, count, \ + errs) +#define GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(desc, errs, count) \ + grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, count, \ + errs) + +// Consumes all the errors in the vector and forms a referencing error from +// them. If the vector is empty, return GRPC_ERROR_NONE. +template <typename VectorType> +static absl::Status grpc_status_create_from_vector( + const grpc_core::DebugLocation& location, const char* desc, + VectorType* error_list) { + absl::Status error = GRPC_ERROR_NONE; + if (error_list->size() != 0) { + error = grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, + error_list->size(), error_list->data()); + error_list->clear(); + } + return error; +} + +#define GRPC_ERROR_CREATE_FROM_VECTOR(desc, error_list) \ + grpc_status_create_from_vector(DEBUG_LOCATION, desc, error_list) + +absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err, + const char* call_name) GRPC_MUST_USE_RESULT; + +inline absl::Status grpc_assert_never_ok(absl::Status error) { + GPR_ASSERT(error != GRPC_ERROR_NONE); + return error; +} + +/// create an error associated with errno!=0 (an 'operating system' error) +#define GRPC_OS_ERROR(err, call_name) \ + grpc_assert_never_ok(grpc_os_error(DEBUG_LOCATION, err, call_name)) + +absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err, + const char* call_name) GRPC_MUST_USE_RESULT; + +/// windows only: create an error associated with WSAGetLastError()!=0 +#define GRPC_WSA_ERROR(err, call_name) \ + grpc_wsa_error(DEBUG_LOCATION, err, call_name) + +#else // GRPC_ERROR_IS_ABSEIL_STATUS + /// The following "special" errors can be propagated without allocating memory. /// They are always even so that other code (particularly combiner locks, /// polling engines) can safely use the lower bit for themselves. -#define GRPC_ERROR_NONE ((grpc_error*)NULL) -#define GRPC_ERROR_RESERVED_1 ((grpc_error*)1) -#define GRPC_ERROR_OOM ((grpc_error*)2) -#define GRPC_ERROR_RESERVED_2 ((grpc_error*)3) -#define GRPC_ERROR_CANCELLED ((grpc_error*)4) +#define GRPC_ERROR_NONE ((grpc_error_handle)NULL) +#define GRPC_ERROR_RESERVED_1 ((grpc_error_handle)1) +#define GRPC_ERROR_OOM ((grpc_error_handle)2) +#define GRPC_ERROR_RESERVED_2 ((grpc_error_handle)3) +#define GRPC_ERROR_CANCELLED ((grpc_error_handle)4) #define GRPC_ERROR_SPECIAL_MAX GRPC_ERROR_CANCELLED -inline bool grpc_error_is_special(struct grpc_error* err) { +inline bool grpc_error_is_special(grpc_error_handle err) { return err <= GRPC_ERROR_SPECIAL_MAX; } -// debug only toggles that allow for a sanity to check that ensures we will -// never create any errors in the per-RPC hotpath. -void grpc_disable_error_creation(); -void grpc_enable_error_creation(); - -const char* grpc_error_string(grpc_error* error); +#ifndef NDEBUG +grpc_error_handle grpc_error_do_ref(grpc_error_handle err, const char* file, + int line); +void grpc_error_do_unref(grpc_error_handle err, const char* file, int line); +inline grpc_error_handle grpc_error_ref(grpc_error_handle err, const char* file, + int line) { + if (grpc_error_is_special(err)) return err; + return grpc_error_do_ref(err, file, line); +} +inline void grpc_error_unref(grpc_error_handle err, const char* file, + int line) { + if (grpc_error_is_special(err)) return; + grpc_error_do_unref(err, file, line); +} +#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__) +#define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__) +#else +grpc_error_handle grpc_error_do_ref(grpc_error_handle err); +void grpc_error_do_unref(grpc_error_handle err); +inline grpc_error_handle grpc_error_ref(grpc_error_handle err) { + if (grpc_error_is_special(err)) return err; + return grpc_error_do_ref(err); +} +inline void grpc_error_unref(grpc_error_handle err) { + if (grpc_error_is_special(err)) return; + grpc_error_do_unref(err); +} +#define GRPC_ERROR_REF(err) grpc_error_ref(err) +#define GRPC_ERROR_UNREF(err) grpc_error_unref(err) +#endif /// Create an error - but use GRPC_ERROR_CREATE instead -grpc_error* grpc_error_create(const char* file, int line, - const grpc_slice& desc, grpc_error** referencing, - size_t num_referencing); +grpc_error_handle grpc_error_create(const char* file, int line, + const grpc_slice& desc, + grpc_error_handle* referencing, + size_t num_referencing); /// Create an error (this is the preferred way of generating an error that is /// not due to a system call - for system calls, use GRPC_OS_ERROR or /// GRPC_WSA_ERROR as appropriate) @@ -157,6 +286,10 @@ grpc_error* grpc_error_create(const char* file, int line, #define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc) \ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \ NULL, 0) +#define GRPC_ERROR_CREATE_FROM_STRING_VIEW(desc) \ + grpc_error_create( \ + __FILE__, __LINE__, \ + grpc_slice_from_copied_buffer((desc).data(), (desc).size()), NULL, 0) // Create an error that references some other errors. This function adds a // reference to each error in errs - it does not consume an existing reference @@ -170,41 +303,14 @@ grpc_error* grpc_error_create(const char* file, int line, #define GRPC_ERROR_CREATE_FROM_VECTOR(desc, error_list) \ grpc_error_create_from_vector(__FILE__, __LINE__, desc, error_list) -#ifndef NDEBUG -grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line); -void grpc_error_do_unref(grpc_error* err, const char* file, int line); -inline grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) { - if (grpc_error_is_special(err)) return err; - return grpc_error_do_ref(err, file, line); -} -inline void grpc_error_unref(grpc_error* err, const char* file, int line) { - if (grpc_error_is_special(err)) return; - grpc_error_do_unref(err, file, line); -} -#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__) -#define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__) -#else -grpc_error* grpc_error_do_ref(grpc_error* err); -void grpc_error_do_unref(grpc_error* err); -inline grpc_error* grpc_error_ref(grpc_error* err) { - if (grpc_error_is_special(err)) return err; - return grpc_error_do_ref(err); -} -inline void grpc_error_unref(grpc_error* err) { - if (grpc_error_is_special(err)) return; - grpc_error_do_unref(err); -} -#define GRPC_ERROR_REF(err) grpc_error_ref(err) -#define GRPC_ERROR_UNREF(err) grpc_error_unref(err) -#endif - // Consumes all the errors in the vector and forms a referencing error from // them. If the vector is empty, return GRPC_ERROR_NONE. template <typename VectorType> -static grpc_error* grpc_error_create_from_vector(const char* file, int line, - const char* desc, - VectorType* error_list) { - grpc_error* error = GRPC_ERROR_NONE; +static grpc_error_handle grpc_error_create_from_vector(const char* file, + int line, + const char* desc, + VectorType* error_list) { + grpc_error_handle error = GRPC_ERROR_NONE; if (error_list->size() != 0) { error = grpc_error_create(file, line, grpc_slice_from_static_string(desc), error_list->data(), error_list->size()); @@ -217,18 +323,40 @@ static grpc_error* grpc_error_create_from_vector(const char* file, int line, return error; } -grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which, - intptr_t value) GRPC_MUST_USE_RESULT; -/// It is an error to pass nullptr as `p`. Caller should allocate a dummy +grpc_error_handle grpc_os_error(const char* file, int line, int err, + const char* call_name) GRPC_MUST_USE_RESULT; + +inline grpc_error_handle grpc_assert_never_ok(grpc_error_handle error) { + GPR_ASSERT(error != GRPC_ERROR_NONE); + return error; +} + +/// create an error associated with errno!=0 (an 'operating system' error) +#define GRPC_OS_ERROR(err, call_name) \ + grpc_assert_never_ok(grpc_os_error(__FILE__, __LINE__, err, call_name)) +grpc_error_handle grpc_wsa_error(const char* file, int line, int err, + const char* call_name) GRPC_MUST_USE_RESULT; +/// windows only: create an error associated with WSAGetLastError()!=0 +#define GRPC_WSA_ERROR(err, call_name) \ + grpc_wsa_error(__FILE__, __LINE__, err, call_name) + +#endif // GRPC_ERROR_IS_ABSEIL_STATUS + +grpc_error_handle grpc_error_set_int(grpc_error_handle src, + grpc_error_ints which, + intptr_t value) GRPC_MUST_USE_RESULT; +/// It is an error to pass nullptr as `p`. Caller should allocate a phony /// intptr_t for `p`, even if the value of `p` is not used. -bool grpc_error_get_int(grpc_error* error, grpc_error_ints which, intptr_t* p); +bool grpc_error_get_int(grpc_error_handle error, grpc_error_ints which, + intptr_t* p); /// This call takes ownership of the slice; the error is responsible for /// eventually unref-ing it. -grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which, - const grpc_slice& str) GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_error_set_str( + grpc_error_handle src, grpc_error_strs which, + const grpc_slice& str) GRPC_MUST_USE_RESULT; /// Returns false if the specified string is not set. /// Caller does NOT own the slice. -bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, +bool grpc_error_get_str(grpc_error_handle error, grpc_error_strs which, grpc_slice* s); /// Add a child error: an error that is believed to have contributed to this @@ -242,29 +370,12 @@ bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, /// returns GRPC_ERROR_NONE. 3) If \a src and \a child point to the same error, /// returns a single reference. (Note that, 2 references should have been /// received to the error in this case.) -grpc_error* grpc_error_add_child(grpc_error* src, - grpc_error* child) GRPC_MUST_USE_RESULT; - -grpc_error* grpc_os_error(const char* file, int line, int err, - const char* call_name) GRPC_MUST_USE_RESULT; - -inline grpc_error* grpc_assert_never_ok(grpc_error* error) { - GPR_ASSERT(error != GRPC_ERROR_NONE); - return error; -} - -/// create an error associated with errno!=0 (an 'operating system' error) -#define GRPC_OS_ERROR(err, call_name) \ - grpc_assert_never_ok(grpc_os_error(__FILE__, __LINE__, err, call_name)) -grpc_error* grpc_wsa_error(const char* file, int line, int err, - const char* call_name) GRPC_MUST_USE_RESULT; -/// windows only: create an error associated with WSAGetLastError()!=0 -#define GRPC_WSA_ERROR(err, call_name) \ - grpc_wsa_error(__FILE__, __LINE__, err, call_name) +grpc_error_handle grpc_error_add_child( + grpc_error_handle src, grpc_error_handle child) GRPC_MUST_USE_RESULT; -bool grpc_log_error(const char* what, grpc_error* error, const char* file, +bool grpc_log_error(const char* what, grpc_error_handle error, const char* file, int line); -inline bool grpc_log_if_error(const char* what, grpc_error* error, +inline bool grpc_log_if_error(const char* what, grpc_error_handle error, const char* file, int line) { return error == GRPC_ERROR_NONE ? true : grpc_log_error(what, error, file, line); |