aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c15
-rw-r--r--src/core/lib/surface/call.c39
2 files changed, 38 insertions, 16 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 855e490bc5..a37b53e8cd 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -889,12 +889,9 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
}
static bool contains_non_ok_status(grpc_metadata_batch *batch) {
- grpc_linked_mdelem *l;
- for (l = batch->list.head; l; l = l->next) {
- if (grpc_slice_eq(GRPC_MDKEY(l->md), GRPC_MDSTR_GRPC_STATUS) &&
- !grpc_mdelem_eq(l->md, GRPC_MDELEM_GRPC_STATUS_0)) {
- return true;
- }
+ if (batch->idx.named.grpc_status != NULL) {
+ return !grpc_mdelem_eq(batch->idx.named.grpc_status->md,
+ GRPC_MDELEM_GRPC_STATUS_0);
}
return false;
}
@@ -1078,9 +1075,13 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
s->fetching_send_message_finished = add_closure_barrier(op->on_complete);
if (s->write_closed) {
+ gpr_log(GPR_DEBUG, "write_closed_error=%s",
+ grpc_error_string(s->write_closed_error));
grpc_chttp2_complete_closure_step(
exec_ctx, t, s, &s->fetching_send_message_finished,
- GRPC_ERROR_CREATE("Attempt to send message after stream was closed"),
+ GRPC_ERROR_CREATE_REFERENCING(
+ "Attempt to send message after stream was closed",
+ &s->write_closed_error, 1),
"fetching_send_message_finished");
} else {
GPR_ASSERT(s->fetching_send_message == NULL);
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 0d63ef051a..830795fc78 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -595,25 +595,46 @@ static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
* FINAL STATUS CODE MANIPULATION
*/
+static void get_final_status_from(grpc_call *call, status_source from_source,
+ void (*set_value)(grpc_status_code code,
+ void *user_data),
+ void *set_value_user_data,
+ grpc_slice *details) {
+ grpc_status_code code;
+ const char *msg = NULL;
+ grpc_error_get_status(call->status[from_source].error, call->send_deadline,
+ &code, &msg, NULL);
+
+ set_value(code, set_value_user_data);
+ if (details != NULL) {
+ *details = grpc_slice_from_copied_string(msg);
+ }
+}
+
static void get_final_status(grpc_call *call,
void (*set_value)(grpc_status_code code,
void *user_data),
void *set_value_user_data, grpc_slice *details) {
int i;
+ /* search for the best status we can present: ideally the error we use has a
+ clearly defined grpc-status, and we'll prefer that. */
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+ if (call->status[i].is_set &&
+ grpc_error_has_clear_grpc_status(call->status[i].error)) {
+ get_final_status_from(call, (status_source)i, set_value,
+ set_value_user_data, details);
+ return;
+ }
+ }
+ /* If no clearly defined status exists, search for 'anything' */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) {
- grpc_status_code code;
- const char *msg = NULL;
- grpc_error_get_status(call->status[i].error, call->send_deadline, &code,
- &msg, NULL);
-
- set_value(code, set_value_user_data);
- if (details != NULL) {
- *details = grpc_slice_from_copied_string(msg);
- }
+ get_final_status_from(call, (status_source)i, set_value,
+ set_value_user_data, details);
return;
}
}
+ /* If nothing exists, set some default */
if (call->is_client) {
set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
} else {