diff options
-rw-r--r-- | src/core/ext/transport/chttp2/transport/chttp2_transport.c | 15 | ||||
-rw-r--r-- | src/core/lib/surface/call.c | 39 |
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 { |