[iomgr][Windows] Return proper error code to client when connection is reset (#33502)

Fixes #24206 by ensuring that IOCP/socket errors in the iomgr on_read
callback are properly annotated with the gRPC Unavailable status. The
WindowsEventEngine was already doing this correctly (try running the
client with `$env:GRPC_EXPERIMENTS="event_engine_client"`).

This also adds two small cleanups:
* Cleanly prints statuses with their child statuses in a few spots
within the chttp2 transport logging (previously, child messages were
printed with garbled bits)
* Adds friendly names to a subset of WSA errors that we're likely to see
from common operations. The top-level status message will no longer just
say "WSA Error" in many cases.

CC @Hamza-Q
pull/33459/head^2
AJ Heller 2 years ago committed by GitHub
parent 7910554cdd
commit 055158b932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  2. 34
      src/core/lib/iomgr/error.cc
  3. 4
      src/core/lib/iomgr/tcp_windows.cc

@ -1648,8 +1648,8 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
}
static void cancel_pings(grpc_chttp2_transport* t, grpc_error_handle error) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "%p CANCEL PINGS: %s", t, error.ToString().c_str()));
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "%p CANCEL PINGS: %s", t,
grpc_core::StatusToString(error).c_str()));
// callback remaining pings: they're not allowed to call into the transport,
// and maybe they hold resources that need to be freed
grpc_chttp2_ping_queue* pq = &t->ping_queue;
@ -2242,7 +2242,7 @@ void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t,
(close_reads && close_writes)
? "read+write"
: (close_reads ? "read" : (close_writes ? "write" : "nothing??")),
error.ToString().c_str());
grpc_core::StatusToString(error).c_str());
}
if (s->read_closed && s->write_closed) {
// already closed, but we should still fake the status if needed.

@ -70,12 +70,42 @@ absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err,
}
#ifdef GPR_WINDOWS
std::string WSAErrorToShortDescription(int err) {
switch (err) {
case WSAEACCES:
return "Permission denied";
case WSAEFAULT:
return "Bad address";
case WSAEMFILE:
return "Too many open files";
case WSAEMSGSIZE:
return "Message too long";
case WSAENETDOWN:
return "Network is down";
case WSAENETUNREACH:
return "Network is unreachable";
case WSAENETRESET:
return "Network dropped connection on reset";
case WSAECONNABORTED:
return "Connection aborted";
case WSAECONNRESET:
return "Connection reset";
case WSAETIMEDOUT:
return "Connection timed out";
case WSAECONNREFUSED:
return "Connection refused";
case WSAEHOSTUNREACH:
return "No route to host";
default:
return "WSA Error";
};
}
// TODO(veblush): lift out of iomgr for use in the WindowsEventEngine
absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err,
absl::string_view call_name) {
char* utf8_message = gpr_format_message(err);
absl::Status s =
StatusCreate(absl::StatusCode::kUnavailable, "WSA Error", location, {});
absl::Status s = StatusCreate(absl::StatusCode::kUnavailable,
WSAErrorToShortDescription(err), location, {});
StatusSetInt(&s, grpc_core::StatusIntProperty::kWsaError, err);
StatusSetInt(&s, grpc_core::StatusIntProperty::kRpcStatus,
GRPC_STATUS_UNAVAILABLE);

@ -186,9 +186,7 @@ static void on_read(void* tcpp, grpc_error_handle error) {
if (error.ok()) {
if (info->wsa_error != 0 && !tcp->shutting_down) {
char* utf8_message = gpr_format_message(info->wsa_error);
error = GRPC_ERROR_CREATE(utf8_message);
gpr_free(utf8_message);
error = GRPC_WSA_ERROR(info->wsa_error, "IOCP/Socket");
grpc_slice_buffer_reset_and_unref(tcp->read_slices);
} else {
if (info->bytes_transferred != 0 && !tcp->shutting_down) {

Loading…
Cancel
Save