grpc 0.15.0 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +127 -159
  3. data/etc/roots.pem +784 -509
  4. data/include/grpc/grpc_posix.h +8 -0
  5. data/include/grpc/impl/codegen/byte_buffer.h +5 -4
  6. data/include/grpc/impl/codegen/grpc_types.h +2 -0
  7. data/include/grpc/impl/codegen/port_platform.h +2 -1
  8. data/include/grpc/module.modulemap +15 -0
  9. data/src/core/ext/census/grpc_filter.c +3 -0
  10. data/src/core/ext/client_config/channel_connectivity.c +4 -3
  11. data/src/core/ext/client_config/client_channel.c +6 -0
  12. data/src/core/ext/client_config/subchannel.c +2 -0
  13. data/src/core/ext/client_config/subchannel_call_holder.c +2 -5
  14. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +2 -1
  15. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +2 -1
  16. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +171 -104
  17. data/src/core/ext/transport/chttp2/transport/internal.h +5 -3
  18. data/src/core/ext/transport/chttp2/transport/parsing.c +4 -3
  19. data/src/core/ext/transport/chttp2/transport/status_conversion.c +8 -2
  20. data/src/core/ext/transport/chttp2/transport/status_conversion.h +1 -1
  21. data/src/core/lib/channel/channel_stack.c +12 -1
  22. data/src/core/lib/channel/channel_stack.h +5 -0
  23. data/src/core/lib/channel/http_client_filter.c +7 -1
  24. data/src/core/lib/debug/trace.c +6 -2
  25. data/src/core/lib/iomgr/error.c +62 -19
  26. data/src/core/lib/iomgr/error.h +10 -6
  27. data/src/core/lib/iomgr/ev_epoll_linux.c +1872 -0
  28. data/src/core/lib/{surface/surface_trace.h → iomgr/ev_epoll_linux.h} +11 -12
  29. data/src/core/lib/iomgr/ev_posix.c +9 -6
  30. data/src/core/lib/iomgr/ev_posix.h +3 -0
  31. data/src/core/lib/iomgr/network_status_tracker.c +121 -0
  32. data/{include/grpc/grpc_zookeeper.h → src/core/lib/iomgr/network_status_tracker.h} +8 -26
  33. data/src/core/lib/iomgr/socket_utils_common_posix.c +22 -0
  34. data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
  35. data/src/core/lib/iomgr/tcp_posix.c +6 -2
  36. data/src/core/lib/iomgr/tcp_server.h +3 -0
  37. data/src/core/lib/iomgr/tcp_server_posix.c +114 -16
  38. data/src/core/lib/iomgr/tcp_server_windows.c +1 -0
  39. data/src/core/lib/iomgr/tcp_windows.c +5 -0
  40. data/src/core/lib/iomgr/udp_server.c +28 -16
  41. data/src/core/lib/iomgr/wakeup_fd_eventfd.c +4 -2
  42. data/src/core/lib/profiling/basic_timers.c +4 -4
  43. data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -3
  44. data/src/core/lib/security/credentials/credentials.c +1 -1
  45. data/src/core/lib/security/credentials/credentials.h +4 -5
  46. data/src/core/lib/security/credentials/fake/fake_credentials.c +2 -2
  47. data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -1
  48. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +7 -6
  49. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +6 -4
  50. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +4 -3
  51. data/src/core/lib/security/transport/client_auth_filter.c +10 -7
  52. data/src/core/lib/surface/byte_buffer_reader.c +6 -4
  53. data/src/core/lib/surface/call.c +64 -51
  54. data/src/core/lib/surface/call.h +0 -1
  55. data/src/core/lib/surface/channel.c +10 -8
  56. data/src/core/lib/surface/completion_queue.c +26 -12
  57. data/src/core/lib/surface/completion_queue.h +4 -0
  58. data/src/core/lib/surface/init.c +6 -1
  59. data/src/core/lib/surface/version.c +1 -1
  60. data/src/core/lib/transport/transport.c +62 -29
  61. data/src/core/lib/transport/transport.h +8 -5
  62. data/src/core/lib/transport/transport_op_string.c +14 -3
  63. data/src/ruby/ext/grpc/rb_byte_buffer.c +4 -1
  64. data/src/ruby/ext/grpc/rb_call.c +87 -54
  65. data/src/ruby/ext/grpc/rb_call.h +1 -1
  66. data/src/ruby/ext/grpc/rb_call_credentials.c +1 -30
  67. data/src/ruby/ext/grpc/rb_channel.c +25 -50
  68. data/src/ruby/ext/grpc/rb_channel_credentials.c +1 -31
  69. data/src/ruby/ext/grpc/rb_completion_queue.c +15 -134
  70. data/src/ruby/ext/grpc/rb_completion_queue.h +3 -7
  71. data/src/ruby/ext/grpc/rb_grpc.c +2 -4
  72. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  73. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  74. data/src/ruby/ext/grpc/rb_server.c +81 -133
  75. data/src/ruby/ext/grpc/rb_server_credentials.c +4 -33
  76. data/src/ruby/lib/grpc/generic/active_call.rb +40 -55
  77. data/src/ruby/lib/grpc/generic/bidi_call.rb +21 -23
  78. data/src/ruby/lib/grpc/generic/client_stub.rb +20 -15
  79. data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -37
  80. data/src/ruby/lib/grpc/generic/service.rb +1 -1
  81. data/src/ruby/lib/grpc/version.rb +1 -1
  82. data/src/ruby/pb/test/client.rb +25 -7
  83. data/src/ruby/pb/test/server.rb +7 -5
  84. data/src/ruby/spec/call_spec.rb +1 -2
  85. data/src/ruby/spec/channel_spec.rb +2 -3
  86. data/src/ruby/spec/client_server_spec.rb +74 -59
  87. data/src/ruby/spec/generic/active_call_spec.rb +66 -86
  88. data/src/ruby/spec/generic/client_stub_spec.rb +27 -48
  89. data/src/ruby/spec/generic/rpc_server_spec.rb +4 -34
  90. data/src/ruby/spec/pb/health/checker_spec.rb +0 -2
  91. data/src/ruby/spec/server_spec.rb +20 -24
  92. metadata +9 -8
  93. data/src/ruby/spec/completion_queue_spec.rb +0 -42
@@ -63,6 +63,14 @@ GRPCAPI void grpc_server_add_insecure_channel_from_fd(grpc_server *server,
63
63
  grpc_completion_queue *cq,
64
64
  int fd);
65
65
 
66
+ /** GRPC Core POSIX library may internally use signals to optimize some work.
67
+ The library uses (SIGRTMIN + 2) signal by default. Use this API to instruct
68
+ the library to use a different signal i.e 'signum' instead.
69
+ Note:
70
+ - To prevent GRPC library from using any signals, pass a 'signum' of -1
71
+ - This API is optional but if called, it MUST be called before grpc_init() */
72
+ GRPCAPI void grpc_use_signal(int signum);
73
+
66
74
  #ifdef __cplusplus
67
75
  }
68
76
  #endif
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  *
3
- * Copyright 2015, Google Inc.
3
+ * Copyright 2015-2016, Google Inc.
4
4
  * All rights reserved.
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
@@ -93,9 +93,10 @@ GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer);
93
93
  struct grpc_byte_buffer_reader;
94
94
  typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader;
95
95
 
96
- /** Initialize \a reader to read over \a buffer */
97
- GRPCAPI void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
98
- grpc_byte_buffer *buffer);
96
+ /** Initialize \a reader to read over \a buffer.
97
+ * Returns 1 upon success, 0 otherwise. */
98
+ GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
99
+ grpc_byte_buffer *buffer);
99
100
 
100
101
  /** Cleanup and destroy \a reader */
101
102
  GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader);
@@ -156,6 +156,8 @@ typedef struct {
156
156
  #define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override"
157
157
  /* Maximum metadata size */
158
158
  #define GRPC_ARG_MAX_METADATA_SIZE "grpc.max_metadata_size"
159
+ /** If non-zero, allow the use of SO_REUSEPORT if it's available (default 1) */
160
+ #define GRPC_ARG_ALLOW_REUSEPORT "grpc.so_reuseport"
159
161
 
160
162
  /** Result of a grpc call. If the caller satisfies the prerequisites of a
161
163
  particular operation, the grpc_call_error returned will be GRPC_CALL_OK.
@@ -119,7 +119,7 @@
119
119
  // libraries; it should be integrated with the `__linux__` definitions below.
120
120
  #define GPR_PLATFORM_STRING "manylinux"
121
121
  #define GPR_POSIX_CRASH_HANDLER 1
122
- #define GPR_CPU_LINUX 1
122
+ #define GPR_CPU_POSIX 1
123
123
  #define GPR_GCC_ATOMIC 1
124
124
  #define GPR_GCC_TLS 1
125
125
  #define GPR_LINUX 1
@@ -207,6 +207,7 @@
207
207
  #ifdef __GLIBC_PREREQ
208
208
  #if __GLIBC_PREREQ(2, 9)
209
209
  #define GPR_LINUX_EVENTFD 1
210
+ #define GPR_LINUX_EPOLL 1
210
211
  #endif
211
212
  #if __GLIBC_PREREQ(2, 10)
212
213
  #define GPR_LINUX_SOCKETUTILS 1
@@ -0,0 +1,15 @@
1
+ framework module grpc {
2
+ umbrella header "grpc.h"
3
+
4
+ header "byte_buffer_reader.h"
5
+ header "grpc_security.h"
6
+ header "grpc_security_constants.h"
7
+ header "impl/codegen/alloc.h"
8
+ header "impl/codegen/byte_buffer_reader.h"
9
+ header "support/alloc.h"
10
+ header "support/port_platform.h"
11
+ header "support/string_util.h"
12
+
13
+ export *
14
+ module * { export * }
15
+ }
@@ -45,6 +45,7 @@
45
45
  #include "src/core/ext/census/census_interface.h"
46
46
  #include "src/core/ext/census/census_rpc_stats.h"
47
47
  #include "src/core/lib/channel/channel_stack.h"
48
+ #include "src/core/lib/profiling/timers.h"
48
49
  #include "src/core/lib/transport/static_metadata.h"
49
50
 
50
51
  typedef struct call_data {
@@ -92,6 +93,7 @@ static void client_start_transport_op(grpc_exec_ctx *exec_ctx,
92
93
 
93
94
  static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
94
95
  grpc_error *error) {
96
+ GPR_TIMER_BEGIN("census-server:server_on_done_recv", 0);
95
97
  grpc_call_element *elem = ptr;
96
98
  call_data *calld = elem->call_data;
97
99
  channel_data *chand = elem->channel_data;
@@ -99,6 +101,7 @@ static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
99
101
  extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand);
100
102
  }
101
103
  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error);
104
+ GPR_TIMER_END("census-server:server_on_done_recv", 0);
102
105
  }
103
106
 
104
107
  static void server_mutate_op(grpc_call_element *elem,
@@ -189,10 +189,11 @@ void grpc_channel_watch_connectivity_state(
189
189
  GRPC_API_TRACE(
190
190
  "grpc_channel_watch_connectivity_state("
191
191
  "channel=%p, last_observed_state=%d, "
192
- "deadline=gpr_timespec { tv_sec: %"PRId64", tv_nsec: %d, clock_type: %d }, "
192
+ "deadline=gpr_timespec { tv_sec: %" PRId64
193
+ ", tv_nsec: %d, clock_type: %d }, "
193
194
  "cq=%p, tag=%p)",
194
- 7, (channel, (int)last_observed_state, deadline.tv_sec,
195
- deadline.tv_nsec, (int)deadline.clock_type, cq, tag));
195
+ 7, (channel, (int)last_observed_state, deadline.tv_sec, deadline.tv_nsec,
196
+ (int)deadline.clock_type, cq, tag));
196
197
 
197
198
  grpc_cq_begin_op(cq, tag);
198
199
 
@@ -367,6 +367,8 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
367
367
  uint32_t initial_metadata_flags,
368
368
  grpc_connected_subchannel **connected_subchannel,
369
369
  grpc_closure *on_ready) {
370
+ GPR_TIMER_BEGIN("cc_pick_subchannel", 0);
371
+
370
372
  grpc_call_element *elem = elemp;
371
373
  channel_data *chand = elem->channel_data;
372
374
  call_data *calld = elem->call_data;
@@ -391,6 +393,7 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
391
393
  }
392
394
  }
393
395
  gpr_mu_unlock(&chand->mu_config);
396
+ GPR_TIMER_END("cc_pick_subchannel", 0);
394
397
  return 1;
395
398
  }
396
399
  if (chand->lb_policy != NULL) {
@@ -402,6 +405,7 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
402
405
  initial_metadata, initial_metadata_flags,
403
406
  connected_subchannel, on_ready);
404
407
  GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
408
+ GPR_TIMER_END("cc_pick_subchannel", 0);
405
409
  return r;
406
410
  }
407
411
  if (chand->resolver != NULL && !chand->started_resolving) {
@@ -426,6 +430,8 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
426
430
  NULL);
427
431
  }
428
432
  gpr_mu_unlock(&chand->mu_config);
433
+
434
+ GPR_TIMER_END("cc_pick_subchannel", 0);
429
435
  return 0;
430
436
  }
431
437
 
@@ -690,9 +690,11 @@ char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
690
690
  void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
691
691
  grpc_subchannel_call *call,
692
692
  grpc_transport_stream_op *op) {
693
+ GPR_TIMER_BEGIN("grpc_subchannel_call_process_op", 0);
693
694
  grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
694
695
  grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
695
696
  top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
697
+ GPR_TIMER_END("grpc_subchannel_call_process_op", 0);
696
698
  }
697
699
 
698
700
  grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
@@ -120,16 +120,13 @@ retry:
120
120
  return;
121
121
  }
122
122
  /* if this is a cancellation, then we can raise our cancelled flag */
123
- if (op->cancel_with_status != GRPC_STATUS_OK) {
123
+ if (op->cancel_error != GRPC_ERROR_NONE) {
124
124
  if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, 1)) {
125
125
  goto retry;
126
126
  } else {
127
127
  switch (holder->creation_phase) {
128
128
  case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
129
- fail_locked(exec_ctx, holder,
130
- grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
131
- GRPC_ERROR_INT_GRPC_STATUS,
132
- op->cancel_with_status));
129
+ fail_locked(exec_ctx, holder, GRPC_ERROR_REF(op->cancel_error));
133
130
  break;
134
131
  case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
135
132
  holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
@@ -97,7 +97,8 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
97
97
  goto error;
98
98
  }
99
99
 
100
- err = grpc_tcp_server_create(NULL, &tcp);
100
+ err =
101
+ grpc_tcp_server_create(NULL, grpc_server_get_channel_args(server), &tcp);
101
102
  if (err != GRPC_ERROR_NONE) {
102
103
  goto error;
103
104
  }
@@ -216,7 +216,8 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
216
216
  state = gpr_malloc(sizeof(*state));
217
217
  memset(state, 0, sizeof(*state));
218
218
  grpc_closure_init(&state->destroy_closure, destroy_done, state);
219
- err = grpc_tcp_server_create(&state->destroy_closure, &tcp);
219
+ err = grpc_tcp_server_create(&state->destroy_closure,
220
+ grpc_server_get_channel_args(server), &tcp);
220
221
  if (err != GRPC_ERROR_NONE) {
221
222
  goto error;
222
223
  }
@@ -106,14 +106,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
106
106
  static void cancel_from_api(grpc_exec_ctx *exec_ctx,
107
107
  grpc_chttp2_transport_global *transport_global,
108
108
  grpc_chttp2_stream_global *stream_global,
109
- grpc_status_code status,
110
- gpr_slice *optional_message);
109
+ grpc_error *error);
111
110
 
112
111
  static void close_from_api(grpc_exec_ctx *exec_ctx,
113
112
  grpc_chttp2_transport_global *transport_global,
114
113
  grpc_chttp2_stream_global *stream_global,
115
- grpc_status_code status,
116
- gpr_slice *optional_message);
114
+ grpc_error *error);
117
115
 
118
116
  /** Add endpoint from this transport to pollset */
119
117
  static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx,
@@ -163,8 +161,6 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
163
161
 
164
162
  GPR_ASSERT(t->ep == NULL);
165
163
 
166
- gpr_slice_unref(t->optional_drop_message);
167
-
168
164
  gpr_slice_buffer_destroy(&t->global.qbuf);
169
165
 
170
166
  gpr_slice_buffer_destroy(&t->writing.outbuf);
@@ -266,7 +262,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
266
262
  is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
267
263
  t->parsing.is_first_frame = true;
268
264
  t->writing.is_client = is_client;
269
- t->optional_drop_message = gpr_empty_slice();
270
265
  grpc_connectivity_state_init(
271
266
  &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
272
267
  is_client ? "client_transport" : "server_transport");
@@ -518,6 +513,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
518
513
  &s->global.received_trailing_metadata);
519
514
  grpc_chttp2_data_parser_init(&s->parsing.data_parser);
520
515
  gpr_slice_buffer_init(&s->writing.flow_controlled_buffer);
516
+ s->global.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
521
517
 
522
518
  REF_TRANSPORT(t, "stream");
523
519
 
@@ -594,6 +590,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx,
594
590
  grpc_chttp2_incoming_metadata_buffer_destroy(
595
591
  &s->global.received_trailing_metadata);
596
592
  gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer);
593
+ GRPC_ERROR_UNREF(s->global.removal_error);
597
594
 
598
595
  UNREF_TRANSPORT(exec_ctx, t, "stream");
599
596
 
@@ -642,6 +639,8 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
642
639
  grpc_chttp2_executor_action_header *hdr;
643
640
  grpc_chttp2_executor_action_header *next;
644
641
 
642
+ GPR_TIMER_BEGIN("finish_global_actions", 0);
643
+
645
644
  for (;;) {
646
645
  if (!t->executor.writing_active && !t->closed &&
647
646
  grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) {
@@ -659,7 +658,9 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
659
658
  NULL;
660
659
  gpr_mu_unlock(&t->executor.mu);
661
660
  while (hdr != NULL) {
661
+ GPR_TIMER_BEGIN("chttp2:locked_action", 0);
662
662
  hdr->action(exec_ctx, t, hdr->stream, hdr->arg);
663
+ GPR_TIMER_END("chttp2:locked_action", 0);
663
664
  next = hdr->next;
664
665
  gpr_free(hdr);
665
666
  UNREF_TRANSPORT(exec_ctx, t, "pending_action");
@@ -672,6 +673,8 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
672
673
  gpr_mu_unlock(&t->executor.mu);
673
674
  break;
674
675
  }
676
+
677
+ GPR_TIMER_END("finish_global_actions", 0);
675
678
  }
676
679
 
677
680
  void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
@@ -681,6 +684,8 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
681
684
  void *arg, size_t sizeof_arg) {
682
685
  grpc_chttp2_executor_action_header *hdr;
683
686
 
687
+ GPR_TIMER_BEGIN("grpc_chttp2_run_with_global_lock", 0);
688
+
684
689
  REF_TRANSPORT(t, "run_global");
685
690
  gpr_mu_lock(&t->executor.mu);
686
691
 
@@ -689,7 +694,9 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
689
694
  t->executor.global_active = 1;
690
695
  gpr_mu_unlock(&t->executor.mu);
691
696
 
697
+ GPR_TIMER_BEGIN("chttp2:locked_action", 0);
692
698
  action(exec_ctx, t, optional_stream, arg);
699
+ GPR_TIMER_END("chttp2:locked_action", 0);
693
700
 
694
701
  finish_global_actions(exec_ctx, t);
695
702
  } else {
@@ -726,6 +733,8 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
726
733
  }
727
734
 
728
735
  UNREF_TRANSPORT(exec_ctx, t, "run_global");
736
+
737
+ GPR_TIMER_END("grpc_chttp2_run_with_global_lock", 0);
729
738
  }
730
739
 
731
740
  /*******************************************************************************
@@ -876,7 +885,9 @@ static void maybe_start_some_streams(
876
885
  grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
877
886
  &stream_global)) {
878
887
  cancel_from_api(exec_ctx, transport_global, stream_global,
879
- GRPC_STATUS_UNAVAILABLE, NULL);
888
+ grpc_error_set_int(
889
+ GRPC_ERROR_CREATE("Stream IDs exhausted"),
890
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
880
891
  }
881
892
  }
882
893
 
@@ -958,14 +969,14 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
958
969
  on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
959
970
  }
960
971
 
961
- if (op->cancel_with_status != GRPC_STATUS_OK) {
972
+ if (op->cancel_error != GRPC_ERROR_NONE) {
962
973
  cancel_from_api(exec_ctx, transport_global, stream_global,
963
- op->cancel_with_status, op->optional_close_message);
974
+ GRPC_ERROR_REF(op->cancel_error));
964
975
  }
965
976
 
966
- if (op->close_with_status != GRPC_STATUS_OK) {
977
+ if (op->close_error != GRPC_ERROR_NONE) {
967
978
  close_from_api(exec_ctx, transport_global, stream_global,
968
- op->close_with_status, op->optional_close_message);
979
+ GRPC_ERROR_REF(op->close_error));
969
980
  }
970
981
 
971
982
  if (op->send_initial_metadata != NULL) {
@@ -978,13 +989,22 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
978
989
  const size_t metadata_peer_limit =
979
990
  transport_global->settings[GRPC_PEER_SETTINGS]
980
991
  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
992
+ if (transport_global->is_client) {
993
+ stream_global->deadline =
994
+ gpr_time_min(stream_global->deadline,
995
+ stream_global->send_initial_metadata->deadline);
996
+ }
981
997
  if (metadata_size > metadata_peer_limit) {
982
- gpr_log(GPR_DEBUG,
983
- "to-be-sent initial metadata size exceeds peer limit "
984
- "(%" PRIuPTR " vs. %" PRIuPTR ")",
985
- metadata_size, metadata_peer_limit);
986
- cancel_from_api(exec_ctx, transport_global, stream_global,
987
- GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
998
+ cancel_from_api(
999
+ exec_ctx, transport_global, stream_global,
1000
+ grpc_error_set_int(
1001
+ grpc_error_set_int(
1002
+ grpc_error_set_int(
1003
+ GRPC_ERROR_CREATE("to-be-sent initial metadata size "
1004
+ "exceeds peer limit"),
1005
+ GRPC_ERROR_INT_SIZE, (intptr_t)metadata_size),
1006
+ GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit),
1007
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
988
1008
  } else {
989
1009
  if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
990
1010
  stream_global->seen_error = true;
@@ -1038,12 +1058,16 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
1038
1058
  transport_global->settings[GRPC_PEER_SETTINGS]
1039
1059
  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1040
1060
  if (metadata_size > metadata_peer_limit) {
1041
- gpr_log(GPR_DEBUG,
1042
- "to-be-sent trailing metadata size exceeds peer limit "
1043
- "(%" PRIuPTR " vs. %" PRIuPTR ")",
1044
- metadata_size, metadata_peer_limit);
1045
- cancel_from_api(exec_ctx, transport_global, stream_global,
1046
- GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
1061
+ cancel_from_api(
1062
+ exec_ctx, transport_global, stream_global,
1063
+ grpc_error_set_int(
1064
+ grpc_error_set_int(
1065
+ grpc_error_set_int(
1066
+ GRPC_ERROR_CREATE("to-be-sent trailing metadata size "
1067
+ "exceeds peer limit"),
1068
+ GRPC_ERROR_INT_SIZE, (intptr_t)metadata_size),
1069
+ GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit),
1070
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1047
1071
  } else {
1048
1072
  if (contains_non_ok_status(transport_global,
1049
1073
  op->send_trailing_metadata)) {
@@ -1235,8 +1259,12 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
1235
1259
  incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1236
1260
  }
1237
1261
  if (stream_global->exceeded_metadata_size) {
1238
- cancel_from_api(exec_ctx, transport_global, stream_global,
1239
- GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
1262
+ cancel_from_api(
1263
+ exec_ctx, transport_global, stream_global,
1264
+ grpc_error_set_int(
1265
+ GRPC_ERROR_CREATE(
1266
+ "received initial metadata size exceeds limit"),
1267
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1240
1268
  }
1241
1269
  }
1242
1270
  grpc_chttp2_incoming_metadata_buffer_publish(
@@ -1275,8 +1303,12 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
1275
1303
  incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs);
1276
1304
  }
1277
1305
  if (stream_global->exceeded_metadata_size) {
1278
- cancel_from_api(exec_ctx, transport_global, stream_global,
1279
- GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
1306
+ cancel_from_api(
1307
+ exec_ctx, transport_global, stream_global,
1308
+ grpc_error_set_int(
1309
+ GRPC_ERROR_CREATE(
1310
+ "received trailing metadata size exceeds limit"),
1311
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
1280
1312
  }
1281
1313
  }
1282
1314
  if (stream_global->all_incoming_byte_streams_finished) {
@@ -1316,15 +1348,15 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1316
1348
  }
1317
1349
  if (s->parsing.data_parser.parsing_frame != NULL) {
1318
1350
  grpc_chttp2_incoming_byte_stream_finished(
1319
- exec_ctx, s->parsing.data_parser.parsing_frame,
1320
- GRPC_ERROR_CREATE_REFERENCING("Stream removed", &error, 1), 0);
1351
+ exec_ctx, s->parsing.data_parser.parsing_frame, GRPC_ERROR_REF(error),
1352
+ 0);
1321
1353
  s->parsing.data_parser.parsing_frame = NULL;
1322
1354
  }
1323
1355
 
1324
1356
  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
1325
1357
  close_transport_locked(
1326
- exec_ctx, t,
1327
- GRPC_ERROR_CREATE("Last stream closed after sending GOAWAY"));
1358
+ exec_ctx, t, GRPC_ERROR_CREATE_REFERENCING(
1359
+ "Last stream closed after sending GOAWAY", &error, 1));
1328
1360
  }
1329
1361
  if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
1330
1362
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
@@ -1340,35 +1372,68 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1340
1372
  GRPC_ERROR_UNREF(error);
1341
1373
  }
1342
1374
 
1375
+ static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
1376
+ grpc_chttp2_error_code *http2_error,
1377
+ grpc_status_code *grpc_status) {
1378
+ intptr_t ip_http;
1379
+ intptr_t ip_grpc;
1380
+ bool have_http =
1381
+ grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &ip_http);
1382
+ bool have_grpc =
1383
+ grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &ip_grpc);
1384
+ if (have_http) {
1385
+ *http2_error = (grpc_chttp2_error_code)ip_http;
1386
+ } else if (have_grpc) {
1387
+ *http2_error =
1388
+ grpc_chttp2_grpc_status_to_http2_error((grpc_status_code)ip_grpc);
1389
+ } else {
1390
+ *http2_error = GRPC_CHTTP2_INTERNAL_ERROR;
1391
+ }
1392
+ if (have_grpc) {
1393
+ *grpc_status = (grpc_status_code)ip_grpc;
1394
+ } else if (have_http) {
1395
+ *grpc_status = grpc_chttp2_http2_error_to_grpc_status(
1396
+ (grpc_chttp2_error_code)ip_http, deadline);
1397
+ } else {
1398
+ *grpc_status = GRPC_STATUS_INTERNAL;
1399
+ }
1400
+ }
1401
+
1343
1402
  static void cancel_from_api(grpc_exec_ctx *exec_ctx,
1344
1403
  grpc_chttp2_transport_global *transport_global,
1345
1404
  grpc_chttp2_stream_global *stream_global,
1346
- grpc_status_code status,
1347
- gpr_slice *optional_message) {
1405
+ grpc_error *due_to_error) {
1348
1406
  if (!stream_global->read_closed || !stream_global->write_closed) {
1407
+ grpc_status_code grpc_status;
1408
+ grpc_chttp2_error_code http_error;
1409
+ status_codes_from_error(due_to_error, stream_global->deadline, &http_error,
1410
+ &grpc_status);
1411
+
1349
1412
  if (stream_global->id != 0) {
1350
1413
  gpr_slice_buffer_add(
1351
1414
  &transport_global->qbuf,
1352
- grpc_chttp2_rst_stream_create(
1353
- stream_global->id,
1354
- (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status),
1355
- &stream_global->stats.outgoing));
1415
+ grpc_chttp2_rst_stream_create(stream_global->id, (uint32_t)http_error,
1416
+ &stream_global->stats.outgoing));
1356
1417
  }
1357
1418
 
1358
- if (optional_message) {
1359
- gpr_slice_ref(*optional_message);
1419
+ const char *msg =
1420
+ grpc_error_get_str(due_to_error, GRPC_ERROR_STR_GRPC_MESSAGE);
1421
+ bool free_msg = false;
1422
+ if (msg == NULL) {
1423
+ free_msg = true;
1424
+ msg = grpc_error_string(due_to_error);
1360
1425
  }
1361
- grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
1362
- optional_message);
1426
+ gpr_slice msg_slice = gpr_slice_from_copied_string(msg);
1427
+ grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
1428
+ grpc_status, &msg_slice);
1429
+ if (free_msg) grpc_error_free_string(msg);
1363
1430
  }
1364
- if (status != GRPC_STATUS_OK && !stream_global->seen_error) {
1431
+ if (due_to_error != GRPC_ERROR_NONE && !stream_global->seen_error) {
1365
1432
  stream_global->seen_error = true;
1366
1433
  grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
1367
1434
  }
1368
- grpc_chttp2_mark_stream_closed(
1369
- exec_ctx, transport_global, stream_global, 1, 1,
1370
- grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
1371
- GRPC_ERROR_INT_GRPC_STATUS, status));
1435
+ grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1436
+ 1, due_to_error);
1372
1437
  }
1373
1438
 
1374
1439
  void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
@@ -1451,6 +1516,7 @@ void grpc_chttp2_mark_stream_closed(
1451
1516
  }
1452
1517
  }
1453
1518
  if (stream_global->read_closed && stream_global->write_closed) {
1519
+ stream_global->removal_error = GRPC_ERROR_REF(error);
1454
1520
  if (stream_global->id != 0 &&
1455
1521
  TRANSPORT_FROM_GLOBAL(transport_global)->executor.parsing_active) {
1456
1522
  grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
@@ -1469,15 +1535,18 @@ void grpc_chttp2_mark_stream_closed(
1469
1535
  static void close_from_api(grpc_exec_ctx *exec_ctx,
1470
1536
  grpc_chttp2_transport_global *transport_global,
1471
1537
  grpc_chttp2_stream_global *stream_global,
1472
- grpc_status_code status,
1473
- gpr_slice *optional_message) {
1538
+ grpc_error *error) {
1474
1539
  gpr_slice hdr;
1475
1540
  gpr_slice status_hdr;
1476
1541
  gpr_slice message_pfx;
1477
1542
  uint8_t *p;
1478
1543
  uint32_t len = 0;
1544
+ grpc_status_code grpc_status;
1545
+ grpc_chttp2_error_code http_error;
1546
+ status_codes_from_error(error, stream_global->deadline, &http_error,
1547
+ &grpc_status);
1479
1548
 
1480
- GPR_ASSERT(status >= 0 && (int)status < 100);
1549
+ GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
1481
1550
 
1482
1551
  if (stream_global->id != 0 && !transport_global->is_client) {
1483
1552
  /* Hand roll a header block.
@@ -1487,7 +1556,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1487
1556
  time we got around to sending this, so instead we ignore HPACK
1488
1557
  compression
1489
1558
  and just write the uncompressed bytes onto the wire. */
1490
- status_hdr = gpr_slice_malloc(15 + (status >= 10));
1559
+ status_hdr = gpr_slice_malloc(15 + (grpc_status >= 10));
1491
1560
  p = GPR_SLICE_START_PTR(status_hdr);
1492
1561
  *p++ = 0x40; /* literal header */
1493
1562
  *p++ = 11; /* len(grpc-status) */
@@ -1502,19 +1571,23 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1502
1571
  *p++ = 't';
1503
1572
  *p++ = 'u';
1504
1573
  *p++ = 's';
1505
- if (status < 10) {
1574
+ if (grpc_status < 10) {
1506
1575
  *p++ = 1;
1507
- *p++ = (uint8_t)('0' + status);
1576
+ *p++ = (uint8_t)('0' + grpc_status);
1508
1577
  } else {
1509
1578
  *p++ = 2;
1510
- *p++ = (uint8_t)('0' + (status / 10));
1511
- *p++ = (uint8_t)('0' + (status % 10));
1579
+ *p++ = (uint8_t)('0' + (grpc_status / 10));
1580
+ *p++ = (uint8_t)('0' + (grpc_status % 10));
1512
1581
  }
1513
1582
  GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
1514
1583
  len += (uint32_t)GPR_SLICE_LENGTH(status_hdr);
1515
1584
 
1516
- if (optional_message) {
1517
- GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
1585
+ const char *optional_message =
1586
+ grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
1587
+
1588
+ if (optional_message != NULL) {
1589
+ size_t msg_len = strlen(optional_message);
1590
+ GPR_ASSERT(msg_len < 127);
1518
1591
  message_pfx = gpr_slice_malloc(15);
1519
1592
  p = GPR_SLICE_START_PTR(message_pfx);
1520
1593
  *p++ = 0x40;
@@ -1531,10 +1604,10 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1531
1604
  *p++ = 'a';
1532
1605
  *p++ = 'g';
1533
1606
  *p++ = 'e';
1534
- *p++ = (uint8_t)GPR_SLICE_LENGTH(*optional_message);
1607
+ *p++ = (uint8_t)msg_len;
1535
1608
  GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
1536
1609
  len += (uint32_t)GPR_SLICE_LENGTH(message_pfx);
1537
- len += (uint32_t)GPR_SLICE_LENGTH(*optional_message);
1610
+ len += (uint32_t)msg_len;
1538
1611
  }
1539
1612
 
1540
1613
  hdr = gpr_slice_malloc(9);
@@ -1555,53 +1628,53 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
1555
1628
  if (optional_message) {
1556
1629
  gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
1557
1630
  gpr_slice_buffer_add(&transport_global->qbuf,
1558
- gpr_slice_ref(*optional_message));
1631
+ gpr_slice_from_copied_string(optional_message));
1559
1632
  }
1560
-
1561
1633
  gpr_slice_buffer_add(
1562
1634
  &transport_global->qbuf,
1563
1635
  grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR,
1564
1636
  &stream_global->stats.outgoing));
1565
-
1566
- if (optional_message) {
1567
- gpr_slice_ref(*optional_message);
1568
- }
1569
1637
  }
1570
1638
 
1571
- grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
1572
- optional_message);
1573
- grpc_error *err = GRPC_ERROR_CREATE("Stream closed");
1574
- err = grpc_error_set_int(err, GRPC_ERROR_INT_GRPC_STATUS, status);
1575
- if (optional_message) {
1576
- char *str =
1577
- gpr_dump_slice(*optional_message, GPR_DUMP_HEX | GPR_DUMP_ASCII);
1578
- err = grpc_error_set_str(err, GRPC_ERROR_STR_GRPC_MESSAGE, str);
1579
- gpr_free(str);
1639
+ const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
1640
+ bool free_msg = false;
1641
+ if (msg == NULL) {
1642
+ free_msg = true;
1643
+ msg = grpc_error_string(error);
1580
1644
  }
1645
+ gpr_slice msg_slice = gpr_slice_from_copied_string(msg);
1646
+ grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
1647
+ grpc_status, &msg_slice);
1648
+ if (free_msg) grpc_error_free_string(msg);
1649
+
1581
1650
  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1582
- 1, err);
1651
+ 1, error);
1583
1652
  }
1584
1653
 
1654
+ typedef struct {
1655
+ grpc_exec_ctx *exec_ctx;
1656
+ grpc_error *error;
1657
+ } cancel_stream_cb_args;
1658
+
1585
1659
  static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
1586
1660
  void *user_data,
1587
1661
  grpc_chttp2_stream_global *stream_global) {
1588
- grpc_chttp2_transport *transport = TRANSPORT_FROM_GLOBAL(transport_global);
1589
- cancel_from_api(user_data, transport_global, stream_global,
1590
- GRPC_STATUS_UNAVAILABLE,
1591
- GPR_SLICE_IS_EMPTY(transport->optional_drop_message)
1592
- ? NULL
1593
- : &transport->optional_drop_message);
1662
+ cancel_stream_cb_args *args = user_data;
1663
+ cancel_from_api(args->exec_ctx, transport_global, stream_global,
1664
+ GRPC_ERROR_REF(args->error));
1594
1665
  }
1595
1666
 
1596
- static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
1597
- grpc_chttp2_transport *t) {
1598
- grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
1667
+ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1668
+ grpc_error *error) {
1669
+ cancel_stream_cb_args args = {exec_ctx, error};
1670
+ grpc_chttp2_for_all_streams(&t->global, &args, cancel_stream_cb);
1671
+ GRPC_ERROR_UNREF(error);
1599
1672
  }
1600
1673
 
1601
1674
  static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1602
1675
  grpc_error *error) {
1603
- close_transport_locked(exec_ctx, t, error);
1604
- end_all_the_calls(exec_ctx, t);
1676
+ close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
1677
+ end_all_the_calls(exec_ctx, t, error);
1605
1678
  }
1606
1679
 
1607
1680
  /** update window from a settings change */
@@ -1699,6 +1772,7 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
1699
1772
  static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
1700
1773
  grpc_error *error) {
1701
1774
  grpc_chttp2_transport *t = arg;
1775
+ grpc_error *err = GRPC_ERROR_NONE;
1702
1776
  GPR_TIMER_BEGIN("reading_action.parse", 0);
1703
1777
  size_t i = 0;
1704
1778
  grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
@@ -1707,23 +1781,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
1707
1781
  errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
1708
1782
  t->read_buffer.slices[i]);
1709
1783
  };
1710
- if (i != t->read_buffer.count) {
1711
- gpr_slice_unref(t->optional_drop_message);
1784
+ if (errors[1] == GRPC_ERROR_NONE) {
1785
+ err = GRPC_ERROR_REF(error);
1786
+ } else {
1712
1787
  errors[2] = try_http_parsing(exec_ctx, t);
1713
- if (errors[2] != GRPC_ERROR_NONE) {
1714
- t->optional_drop_message = gpr_slice_from_copied_string(
1715
- "Connection dropped: received http1.x response");
1716
- } else {
1717
- t->optional_drop_message = gpr_slice_from_copied_string(
1718
- "Connection dropped: received unparseable response");
1719
- }
1788
+ err = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
1789
+ GPR_ARRAY_SIZE(errors));
1720
1790
  }
1721
- grpc_error *err =
1722
- errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE &&
1723
- errors[2] == GRPC_ERROR_NONE
1724
- ? GRPC_ERROR_NONE
1725
- : GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
1726
- GPR_ARRAY_SIZE(errors));
1727
1791
  for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
1728
1792
  GRPC_ERROR_UNREF(errors[i]);
1729
1793
  }
@@ -1767,7 +1831,7 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1767
1831
  GPR_ASSERT(stream_global->write_closed);
1768
1832
  GPR_ASSERT(stream_global->read_closed);
1769
1833
  remove_stream(exec_ctx, t, stream_global->id,
1770
- GRPC_ERROR_CREATE("Stream removed"));
1834
+ GRPC_ERROR_REF(stream_global->removal_error));
1771
1835
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
1772
1836
  }
1773
1837
 
@@ -1784,6 +1848,10 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1784
1848
  error = GRPC_ERROR_CREATE("Transport closed");
1785
1849
  }
1786
1850
  if (error != GRPC_ERROR_NONE) {
1851
+ if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
1852
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
1853
+ GRPC_STATUS_UNAVAILABLE);
1854
+ }
1787
1855
  drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
1788
1856
  t->endpoint_reading = 0;
1789
1857
  if (!t->executor.writing_active && t->ep) {
@@ -1798,6 +1866,7 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1798
1866
  prevent_endpoint_shutdown(t);
1799
1867
  }
1800
1868
  gpr_slice_buffer_reset_and_unref(&t->read_buffer);
1869
+ GRPC_ERROR_UNREF(error);
1801
1870
 
1802
1871
  if (keep_reading) {
1803
1872
  grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->reading_action);
@@ -1806,8 +1875,6 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
1806
1875
  } else {
1807
1876
  UNREF_TRANSPORT(exec_ctx, t, "reading_action");
1808
1877
  }
1809
-
1810
- GRPC_LOG_IF_ERROR("close_transport", error);
1811
1878
  }
1812
1879
 
1813
1880
  /*******************************************************************************