Make it more likely to correctly report deadline exceeded
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 38e782b..5aae753 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -513,6 +513,7 @@
&s->global.received_trailing_metadata);
grpc_chttp2_data_parser_init(&s->parsing.data_parser);
gpr_slice_buffer_init(&s->writing.flow_controlled_buffer);
+ s->global.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
REF_TRANSPORT(t, "stream");
@@ -988,6 +989,11 @@
const size_t metadata_peer_limit =
transport_global->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
+ if (transport_global->is_client) {
+ stream_global->deadline =
+ gpr_time_min(stream_global->deadline,
+ stream_global->send_initial_metadata->deadline);
+ }
if (metadata_size > metadata_peer_limit) {
cancel_from_api(
exec_ctx, transport_global, stream_global,
@@ -1366,7 +1372,7 @@
GRPC_ERROR_UNREF(error);
}
-static void status_codes_from_error(grpc_error *error,
+static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
grpc_chttp2_error_code *http2_error,
grpc_status_code *grpc_status) {
intptr_t ip_http;
@@ -1386,8 +1392,8 @@
if (have_grpc) {
*grpc_status = (grpc_status_code)ip_grpc;
} else if (have_http) {
- *grpc_status =
- grpc_chttp2_http2_error_to_grpc_status((grpc_chttp2_error_code)ip_http);
+ *grpc_status = grpc_chttp2_http2_error_to_grpc_status(
+ (grpc_chttp2_error_code)ip_http, deadline);
} else {
*grpc_status = GRPC_STATUS_INTERNAL;
}
@@ -1400,7 +1406,8 @@
if (!stream_global->read_closed || !stream_global->write_closed) {
grpc_status_code grpc_status;
grpc_chttp2_error_code http_error;
- status_codes_from_error(due_to_error, &http_error, &grpc_status);
+ status_codes_from_error(due_to_error, stream_global->deadline, &http_error,
+ &grpc_status);
if (stream_global->id != 0) {
gpr_slice_buffer_add(
@@ -1536,7 +1543,8 @@
uint32_t len = 0;
grpc_status_code grpc_status;
grpc_chttp2_error_code http_error;
- status_codes_from_error(error, &http_error, &grpc_status);
+ status_codes_from_error(error, stream_global->deadline, &http_error,
+ &grpc_status);
GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index b5180c6..8d79e93 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -447,6 +447,8 @@
grpc_chttp2_incoming_metadata_buffer received_trailing_metadata;
grpc_chttp2_incoming_frame_queue incoming_frames;
+
+ gpr_timespec deadline;
} grpc_chttp2_stream_global;
typedef struct {
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 991d772..c5240ce 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -87,8 +87,8 @@
transport_global->settings[GRPC_SENT_SETTINGS],
sizeof(transport_parsing->last_sent_settings));
transport_parsing->max_frame_size =
- transport_global->settings[GRPC_ACKED_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
+ transport_global
+ ->settings[GRPC_ACKED_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
/* update the parsing view of incoming window */
while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
@@ -236,9 +236,10 @@
GRPC_ERROR_INT_HTTP2_ERROR, &reason);
if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) {
grpc_status_code status_code =
- has_reason ? grpc_chttp2_http2_error_to_grpc_status(
- (grpc_chttp2_error_code)reason)
- : GRPC_STATUS_INTERNAL;
+ has_reason
+ ? grpc_chttp2_http2_error_to_grpc_status(
+ (grpc_chttp2_error_code)reason, stream_global->deadline)
+ : GRPC_STATUS_INTERNAL;
const char *status_details =
grpc_error_string(stream_parsing->forced_close_error);
gpr_slice slice_details = gpr_slice_from_copied_string(status_details);
diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.c b/src/core/ext/transport/chttp2/transport/status_conversion.c
index c42fb9b..5dce2f2 100644
--- a/src/core/ext/transport/chttp2/transport/status_conversion.c
+++ b/src/core/ext/transport/chttp2/transport/status_conversion.c
@@ -39,6 +39,8 @@
return GRPC_CHTTP2_NO_ERROR;
case GRPC_STATUS_CANCELLED:
return GRPC_CHTTP2_CANCEL;
+ case GRPC_STATUS_DEADLINE_EXCEEDED:
+ return GRPC_CHTTP2_CANCEL;
case GRPC_STATUS_RESOURCE_EXHAUSTED:
return GRPC_CHTTP2_ENHANCE_YOUR_CALM;
case GRPC_STATUS_PERMISSION_DENIED:
@@ -51,13 +53,17 @@
}
grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
- grpc_chttp2_error_code error) {
+ grpc_chttp2_error_code error, gpr_timespec deadline) {
switch (error) {
case GRPC_CHTTP2_NO_ERROR:
/* should never be received */
return GRPC_STATUS_INTERNAL;
case GRPC_CHTTP2_CANCEL:
- return GRPC_STATUS_CANCELLED;
+ /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been
+ * exceeded */
+ return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0
+ ? GRPC_STATUS_DEADLINE_EXCEEDED
+ : GRPC_STATUS_CANCELLED;
case GRPC_CHTTP2_ENHANCE_YOUR_CALM:
return GRPC_STATUS_RESOURCE_EXHAUSTED;
case GRPC_CHTTP2_INADEQUATE_SECURITY:
diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.h b/src/core/ext/transport/chttp2/transport/status_conversion.h
index e7285e6..953bc9f 100644
--- a/src/core/ext/transport/chttp2/transport/status_conversion.h
+++ b/src/core/ext/transport/chttp2/transport/status_conversion.h
@@ -41,7 +41,7 @@
grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error(
grpc_status_code status);
grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
- grpc_chttp2_error_code error);
+ grpc_chttp2_error_code error, gpr_timespec deadline);
/* Conversion of HTTP status codes (:status) to grpc status codes */
grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status);
diff --git a/test/core/transport/chttp2/status_conversion_test.c b/test/core/transport/chttp2/status_conversion_test.c
index e6fc785..f5a5cd1 100644
--- a/test/core/transport/chttp2/status_conversion_test.c
+++ b/test/core/transport/chttp2/status_conversion_test.c
@@ -37,8 +37,8 @@
#define GRPC_STATUS_TO_HTTP2_ERROR(a, b) \
GPR_ASSERT(grpc_chttp2_grpc_status_to_http2_error(a) == (b))
-#define HTTP2_ERROR_TO_GRPC_STATUS(a, b) \
- GPR_ASSERT(grpc_chttp2_http2_error_to_grpc_status(a) == (b))
+#define HTTP2_ERROR_TO_GRPC_STATUS(a, deadline, b) \
+ GPR_ASSERT(grpc_chttp2_http2_error_to_grpc_status(a, deadline) == (b))
#define GRPC_STATUS_TO_HTTP2_STATUS(a, b) \
GPR_ASSERT(grpc_chttp2_grpc_status_to_http2_status(a) == (b))
#define HTTP2_STATUS_TO_GRPC_STATUS(a, b) \
@@ -54,8 +54,7 @@
GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_CHTTP2_INTERNAL_ERROR);
GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INVALID_ARGUMENT,
GRPC_CHTTP2_INTERNAL_ERROR);
- GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED,
- GRPC_CHTTP2_INTERNAL_ERROR);
+ GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_CHTTP2_CANCEL);
GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_CHTTP2_INTERNAL_ERROR);
GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ALREADY_EXISTS,
GRPC_CHTTP2_INTERNAL_ERROR);
@@ -95,25 +94,60 @@
GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAVAILABLE, 200);
GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DATA_LOSS, 200);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR,
+ const gpr_timespec before_deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, before_deadline,
GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT,
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, before_deadline,
GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR,
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, before_deadline,
GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM,
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR, before_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT, before_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, before_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR, before_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM, before_deadline,
GRPC_STATUS_UNAVAILABLE);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, GRPC_STATUS_CANCELLED);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR,
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, before_deadline,
+ GRPC_STATUS_CANCELLED);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR, before_deadline,
GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, GRPC_STATUS_INTERNAL);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM,
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, before_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM, before_deadline,
GRPC_STATUS_RESOURCE_EXHAUSTED);
- HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY,
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY, before_deadline,
+ GRPC_STATUS_PERMISSION_DENIED);
+
+ const gpr_timespec after_deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM, after_deadline,
+ GRPC_STATUS_UNAVAILABLE);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, after_deadline,
+ GRPC_STATUS_DEADLINE_EXCEEDED);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, after_deadline,
+ GRPC_STATUS_INTERNAL);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM, after_deadline,
+ GRPC_STATUS_RESOURCE_EXHAUSTED);
+ HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY, after_deadline,
GRPC_STATUS_PERMISSION_DENIED);
HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK);