• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2016 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 #include <grpc/support/port_platform.h>
19 
20 #include "src/core/lib/iomgr/error.h"
21 
22 #include <inttypes.h>
23 #include <string.h>
24 
25 #include "absl/strings/str_format.h"
26 
27 #include <grpc/status.h>
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/log.h>
30 #include <grpc/support/string_util.h>
31 
32 #include "src/core/lib/gprpp/crash.h"
33 
34 #ifdef GPR_WINDOWS
35 #include <grpc/support/log_windows.h>
36 #endif
37 
38 #include "src/core/lib/debug/trace.h"
39 #include "src/core/lib/gpr/useful.h"
40 #include "src/core/lib/gprpp/strerror.h"
41 #include "src/core/lib/slice/slice_internal.h"
42 
43 grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount(false,
44                                                         "error_refcount");
45 grpc_core::DebugOnlyTraceFlag grpc_trace_closure(false, "closure");
46 
grpc_status_create(absl::StatusCode code,absl::string_view msg,const grpc_core::DebugLocation & location,size_t children_count,absl::Status * children)47 absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg,
48                                 const grpc_core::DebugLocation& location,
49                                 size_t children_count, absl::Status* children) {
50   absl::Status s = StatusCreate(code, msg, location, {});
51   for (size_t i = 0; i < children_count; ++i) {
52     if (!children[i].ok()) {
53       grpc_core::StatusAddChild(&s, children[i]);
54     }
55   }
56   return s;
57 }
58 
grpc_os_error(const grpc_core::DebugLocation & location,int err,const char * call_name)59 absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err,
60                            const char* call_name) {
61   auto err_string = grpc_core::StrError(err);
62   absl::Status s =
63       StatusCreate(absl::StatusCode::kUnknown, err_string, location, {});
64   grpc_core::StatusSetInt(&s, grpc_core::StatusIntProperty::kErrorNo, err);
65   grpc_core::StatusSetStr(&s, grpc_core::StatusStrProperty::kOsError,
66                           err_string);
67   grpc_core::StatusSetStr(&s, grpc_core::StatusStrProperty::kSyscall,
68                           call_name);
69   return s;
70 }
71 
72 #ifdef GPR_WINDOWS
WSAErrorToShortDescription(int err)73 std::string WSAErrorToShortDescription(int err) {
74   switch (err) {
75     case WSAEACCES:
76       return "Permission denied";
77     case WSAEFAULT:
78       return "Bad address";
79     case WSAEMFILE:
80       return "Too many open files";
81     case WSAEMSGSIZE:
82       return "Message too long";
83     case WSAENETDOWN:
84       return "Network is down";
85     case WSAENETUNREACH:
86       return "Network is unreachable";
87     case WSAENETRESET:
88       return "Network dropped connection on reset";
89     case WSAECONNABORTED:
90       return "Connection aborted";
91     case WSAECONNRESET:
92       return "Connection reset";
93     case WSAETIMEDOUT:
94       return "Connection timed out";
95     case WSAECONNREFUSED:
96       return "Connection refused";
97     case WSAEHOSTUNREACH:
98       return "No route to host";
99     default:
100       return "WSA Error";
101   };
102 }
103 // TODO(veblush): lift out of iomgr for use in the WindowsEventEngine
grpc_wsa_error(const grpc_core::DebugLocation & location,int err,absl::string_view call_name)104 absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err,
105                             absl::string_view call_name) {
106   char* utf8_message = gpr_format_message(err);
107   absl::Status s = StatusCreate(absl::StatusCode::kUnavailable,
108                                 WSAErrorToShortDescription(err), location, {});
109   StatusSetInt(&s, grpc_core::StatusIntProperty::kWsaError, err);
110   StatusSetInt(&s, grpc_core::StatusIntProperty::kRpcStatus,
111                GRPC_STATUS_UNAVAILABLE);
112   StatusSetStr(&s, grpc_core::StatusStrProperty::kOsError, utf8_message);
113   StatusSetStr(&s, grpc_core::StatusStrProperty::kSyscall, call_name);
114   gpr_free(utf8_message);
115   return s;
116 }
117 #endif
118 
grpc_error_set_int(grpc_error_handle src,grpc_core::StatusIntProperty which,intptr_t value)119 grpc_error_handle grpc_error_set_int(grpc_error_handle src,
120                                      grpc_core::StatusIntProperty which,
121                                      intptr_t value) {
122   if (src.ok()) {
123     src = absl::UnknownError("");
124     StatusSetInt(&src, grpc_core::StatusIntProperty::kRpcStatus,
125                  GRPC_STATUS_OK);
126   }
127   grpc_core::StatusSetInt(&src, which, value);
128   return src;
129 }
130 
grpc_error_get_int(grpc_error_handle error,grpc_core::StatusIntProperty which,intptr_t * p)131 bool grpc_error_get_int(grpc_error_handle error,
132                         grpc_core::StatusIntProperty which, intptr_t* p) {
133   absl::optional<intptr_t> value = grpc_core::StatusGetInt(error, which);
134   if (value.has_value()) {
135     *p = *value;
136     return true;
137   } else {
138     // TODO(veblush): Remove this once absl::Status migration is done
139     if (which == grpc_core::StatusIntProperty::kRpcStatus) {
140       switch (error.code()) {
141         case absl::StatusCode::kOk:
142           *p = GRPC_STATUS_OK;
143           return true;
144         case absl::StatusCode::kResourceExhausted:
145           *p = GRPC_STATUS_RESOURCE_EXHAUSTED;
146           return true;
147         case absl::StatusCode::kCancelled:
148           *p = GRPC_STATUS_CANCELLED;
149           return true;
150         default:
151           break;
152       }
153     }
154     return false;
155   }
156 }
157 
grpc_error_set_str(grpc_error_handle src,grpc_core::StatusStrProperty which,absl::string_view str)158 grpc_error_handle grpc_error_set_str(grpc_error_handle src,
159                                      grpc_core::StatusStrProperty which,
160                                      absl::string_view str) {
161   if (src.ok()) {
162     src = absl::UnknownError("");
163     StatusSetInt(&src, grpc_core::StatusIntProperty::kRpcStatus,
164                  GRPC_STATUS_OK);
165   }
166   if (which == grpc_core::StatusStrProperty::kDescription) {
167     // To change the message of absl::Status, a new instance should be created
168     // with a code and payload because it doesn't have a setter for it.
169     absl::Status s = absl::Status(src.code(), str);
170     src.ForEachPayload(
171         [&](absl::string_view type_url, const absl::Cord& payload) {
172           s.SetPayload(type_url, payload);
173         });
174     return s;
175   } else {
176     grpc_core::StatusSetStr(&src, which, str);
177   }
178   return src;
179 }
180 
grpc_error_get_str(grpc_error_handle error,grpc_core::StatusStrProperty which,std::string * s)181 bool grpc_error_get_str(grpc_error_handle error,
182                         grpc_core::StatusStrProperty which, std::string* s) {
183   if (which == grpc_core::StatusStrProperty::kDescription) {
184     // absl::Status uses the message field for
185     // grpc_core::StatusStrProperty::kDescription instead of using payload.
186     absl::string_view msg = error.message();
187     if (msg.empty()) {
188       return false;
189     } else {
190       *s = std::string(msg);
191       return true;
192     }
193   } else {
194     absl::optional<std::string> value = grpc_core::StatusGetStr(error, which);
195     if (value.has_value()) {
196       *s = std::move(*value);
197       return true;
198     } else {
199       // TODO(veblush): Remove this once absl::Status migration is done
200       if (which == grpc_core::StatusStrProperty::kGrpcMessage) {
201         switch (error.code()) {
202           case absl::StatusCode::kOk:
203             *s = "";
204             return true;
205           case absl::StatusCode::kCancelled:
206             *s = "CANCELLED";
207             return true;
208           default:
209             break;
210         }
211       }
212       return false;
213     }
214   }
215 }
216 
grpc_error_add_child(grpc_error_handle src,grpc_error_handle child)217 grpc_error_handle grpc_error_add_child(grpc_error_handle src,
218                                        grpc_error_handle child) {
219   if (src.ok()) {
220     return child;
221   } else {
222     if (!child.ok()) {
223       grpc_core::StatusAddChild(&src, child);
224     }
225     return src;
226   }
227 }
228 
grpc_log_error(const char * what,grpc_error_handle error,const char * file,int line)229 bool grpc_log_error(const char* what, grpc_error_handle error, const char* file,
230                     int line) {
231   GPR_DEBUG_ASSERT(!error.ok());
232   gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what,
233           grpc_core::StatusToString(error).c_str());
234   return false;
235 }
236