grpc 0.13.0 → 0.13.1.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/Makefile +1114 -937
  4. data/include/grpc/census.h +71 -89
  5. data/include/grpc/compression.h +7 -7
  6. data/include/grpc/grpc.h +65 -68
  7. data/include/grpc/grpc_security.h +38 -38
  8. data/include/grpc/impl/codegen/alloc.h +7 -7
  9. data/include/grpc/impl/codegen/byte_buffer.h +13 -13
  10. data/include/grpc/impl/codegen/grpc_types.h +7 -2
  11. data/include/grpc/impl/codegen/log.h +5 -5
  12. data/include/grpc/impl/codegen/port_platform.h +14 -6
  13. data/include/grpc/impl/codegen/slice.h +15 -15
  14. data/include/grpc/impl/codegen/slice_buffer.h +17 -17
  15. data/include/grpc/impl/codegen/sync.h +26 -22
  16. data/include/grpc/impl/codegen/time.h +22 -24
  17. data/include/grpc/support/avl.h +9 -8
  18. data/include/grpc/support/cmdline.h +12 -12
  19. data/include/grpc/support/cpu.h +2 -2
  20. data/include/grpc/support/histogram.h +22 -22
  21. data/include/grpc/support/host_port.h +2 -2
  22. data/include/grpc/support/log_win32.h +1 -1
  23. data/include/grpc/support/string_util.h +2 -2
  24. data/include/grpc/support/subprocess.h +5 -5
  25. data/include/grpc/support/thd.h +9 -9
  26. data/include/grpc/support/useful.h +3 -1
  27. data/src/core/census/context.c +64 -85
  28. data/src/core/census/grpc_filter.c +2 -2
  29. data/src/core/census/mlog.c +600 -0
  30. data/src/core/census/mlog.h +95 -0
  31. data/src/core/channel/channel_args.c +67 -6
  32. data/src/core/channel/channel_args.h +7 -1
  33. data/src/core/channel/client_channel.c +26 -36
  34. data/src/core/channel/client_uchannel.c +1 -1
  35. data/src/core/channel/http_client_filter.c +2 -2
  36. data/src/core/channel/http_server_filter.c +2 -2
  37. data/src/core/channel/subchannel_call_holder.c +5 -7
  38. data/src/core/client_config/connector.c +3 -2
  39. data/src/core/client_config/connector.h +2 -2
  40. data/src/core/client_config/lb_policies/load_balancer_api.c +163 -0
  41. data/src/core/client_config/lb_policies/load_balancer_api.h +85 -0
  42. data/src/core/client_config/lb_policies/pick_first.c +10 -11
  43. data/src/core/client_config/lb_policies/round_robin.c +7 -8
  44. data/src/core/client_config/lb_policy.c +3 -3
  45. data/src/core/client_config/lb_policy.h +3 -2
  46. data/src/core/client_config/subchannel.c +51 -21
  47. data/src/core/client_config/subchannel.h +15 -6
  48. data/src/core/client_config/subchannel_index.c +261 -0
  49. data/src/core/client_config/subchannel_index.h +77 -0
  50. data/src/core/compression/{algorithm.c → compression_algorithm.c} +0 -0
  51. data/src/core/httpcli/httpcli.c +13 -11
  52. data/src/core/httpcli/httpcli.h +3 -2
  53. data/src/core/httpcli/httpcli_security_connector.c +7 -7
  54. data/src/core/iomgr/fd_posix.c +4 -2
  55. data/src/core/iomgr/iocp_windows.c +10 -6
  56. data/src/core/iomgr/iocp_windows.h +9 -2
  57. data/src/core/iomgr/iomgr.c +18 -2
  58. data/src/core/iomgr/iomgr_internal.h +5 -1
  59. data/src/core/iomgr/pollset.h +9 -10
  60. data/src/core/iomgr/pollset_multipoller_with_epoll.c +1 -0
  61. data/src/core/iomgr/pollset_multipoller_with_poll_posix.c +10 -5
  62. data/src/core/iomgr/pollset_posix.c +30 -35
  63. data/src/core/iomgr/pollset_posix.h +10 -6
  64. data/src/core/iomgr/pollset_set.h +3 -9
  65. data/src/core/iomgr/pollset_set_posix.c +23 -3
  66. data/src/core/iomgr/pollset_set_posix.h +2 -18
  67. data/src/core/iomgr/pollset_set_windows.c +3 -3
  68. data/src/core/iomgr/pollset_set_windows.h +2 -2
  69. data/src/core/iomgr/pollset_windows.c +24 -21
  70. data/src/core/iomgr/pollset_windows.h +1 -5
  71. data/src/core/iomgr/tcp_client_posix.c +7 -5
  72. data/src/core/iomgr/tcp_posix.c +4 -2
  73. data/src/core/iomgr/tcp_server_windows.c +1 -2
  74. data/src/core/iomgr/timer.c +2 -3
  75. data/src/core/iomgr/timer.h +21 -1
  76. data/src/core/iomgr/timer_heap.c +10 -12
  77. data/src/core/iomgr/udp_server.c +5 -4
  78. data/src/core/iomgr/udp_server.h +1 -0
  79. data/src/core/iomgr/workqueue_posix.c +1 -0
  80. data/src/core/iomgr/workqueue_posix.h +3 -1
  81. data/src/core/proto/grpc/lb/v0/load_balancer.pb.c +119 -0
  82. data/src/core/proto/grpc/lb/v0/load_balancer.pb.h +182 -0
  83. data/src/core/security/{base64.c → b64.c} +1 -1
  84. data/src/core/security/{base64.h → b64.h} +1 -1
  85. data/src/core/security/client_auth_filter.c +0 -1
  86. data/src/core/security/credentials.c +12 -5
  87. data/src/core/security/credentials.h +3 -3
  88. data/src/core/security/google_default_credentials.c +24 -19
  89. data/src/core/security/handshake.c +15 -7
  90. data/src/core/security/handshake.h +2 -1
  91. data/src/core/security/json_token.c +1 -1
  92. data/src/core/security/jwt_verifier.c +1 -1
  93. data/src/core/security/security_connector.c +84 -64
  94. data/src/core/security/security_connector.h +42 -22
  95. data/src/core/security/security_context.c +8 -3
  96. data/src/core/security/server_auth_filter.c +2 -2
  97. data/src/core/security/server_secure_chttp2.c +7 -7
  98. data/src/core/support/avl.c +2 -2
  99. data/src/core/support/env_linux.c +17 -0
  100. data/src/core/support/{file.c → load_file.c} +2 -2
  101. data/src/core/support/{file.h → load_file.h} +4 -12
  102. data/src/core/support/sync.c +6 -1
  103. data/src/core/support/time_posix.c +1 -1
  104. data/src/core/{iomgr/timer_internal.h → support/tmpfile.h} +17 -23
  105. data/src/core/support/{file_posix.c → tmpfile_posix.c} +2 -2
  106. data/src/core/support/{file_win32.c → tmpfile_win32.c} +2 -2
  107. data/src/core/surface/alarm.c +3 -2
  108. data/src/core/surface/call.c +102 -52
  109. data/src/core/surface/channel_create.c +1 -1
  110. data/src/core/surface/completion_queue.c +73 -41
  111. data/src/core/surface/init.c +4 -0
  112. data/src/core/surface/lame_client.c +1 -2
  113. data/src/core/surface/secure_channel_create.c +6 -7
  114. data/src/core/surface/server.c +13 -5
  115. data/src/core/surface/validate_metadata.c +1 -1
  116. data/src/core/surface/version.c +1 -1
  117. data/src/core/transport/chttp2/internal.h +22 -10
  118. data/src/core/transport/chttp2/parsing.c +3 -3
  119. data/src/core/transport/chttp2/stream_lists.c +39 -21
  120. data/src/core/transport/chttp2/writing.c +19 -28
  121. data/src/core/transport/chttp2_transport.c +80 -37
  122. data/src/core/transport/metadata.c +8 -0
  123. data/src/core/transport/static_metadata.c +17 -17
  124. data/src/core/transport/static_metadata.h +3 -3
  125. data/src/core/transport/transport.c +2 -1
  126. data/src/core/transport/transport.h +12 -5
  127. data/src/ruby/ext/grpc/extconf.rb +1 -0
  128. data/src/ruby/ext/grpc/rb_call.c +6 -0
  129. data/src/ruby/ext/grpc/rb_call_credentials.c +12 -14
  130. data/src/ruby/ext/grpc/rb_channel.c +8 -14
  131. data/src/ruby/ext/grpc/rb_channel_credentials.c +11 -12
  132. data/src/ruby/ext/grpc/rb_grpc.c +19 -18
  133. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -0
  134. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +8 -2
  135. data/src/ruby/lib/grpc/core/time_consts.rb +2 -2
  136. data/src/ruby/lib/grpc/errors.rb +2 -2
  137. data/src/ruby/lib/grpc/generic/rpc_server.rb +58 -39
  138. data/src/ruby/lib/grpc/version.rb +1 -1
  139. data/src/ruby/pb/README.md +2 -2
  140. data/src/ruby/pb/generate_proto_ruby.sh +2 -2
  141. data/src/ruby/pb/grpc/health/checker.rb +11 -11
  142. data/src/ruby/pb/grpc/health/v1/health.rb +28 -0
  143. data/src/ruby/pb/grpc/health/{v1alpha → v1}/health_services.rb +4 -4
  144. data/src/ruby/spec/client_server_spec.rb +2 -1
  145. data/src/ruby/spec/generic/rpc_server_spec.rb +3 -22
  146. data/src/ruby/spec/pb/health/checker_spec.rb +22 -36
  147. data/third_party/nanopb/pb.h +547 -0
  148. data/third_party/nanopb/pb_common.c +97 -0
  149. data/third_party/nanopb/pb_common.h +42 -0
  150. data/third_party/nanopb/pb_decode.c +1319 -0
  151. data/third_party/nanopb/pb_decode.h +149 -0
  152. data/third_party/nanopb/pb_encode.c +690 -0
  153. data/third_party/nanopb/pb_encode.h +154 -0
  154. metadata +32 -16
  155. data/src/ruby/pb/grpc/health/v1alpha/health.rb +0 -29
@@ -79,6 +79,7 @@ unless File.exist?(File.join(grpc_lib_dir, 'libgrpc.a')) or windows
79
79
  ENV['EMBED_ZLIB'] = 'true'
80
80
  ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG']
81
81
  ENV['ARCH_FLAGS'] = '-arch i386 -arch x86_64' if RUBY_PLATFORM =~ /darwin/
82
+ ENV['CFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE'
82
83
 
83
84
  output_dir = File.expand_path(RbConfig::CONFIG['topdir'])
84
85
  grpc_lib_dir = File.join(output_dir, 'libs', grpc_config)
@@ -72,6 +72,10 @@ static ID id_cq;
72
72
  * the flags used to create metadata from a Hash */
73
73
  static ID id_flags;
74
74
 
75
+ /* id_credentials is the name of the hidden ivar that preserves the value
76
+ * of the credentials added to the call */
77
+ static ID id_credentials;
78
+
75
79
  /* id_input_md is the name of the hidden ivar that preserves the hash used to
76
80
  * create metadata, so that references to the strings it contains last as long
77
81
  * as the call the metadata is added to. */
@@ -299,6 +303,7 @@ static VALUE grpc_rb_call_set_credentials(VALUE self, VALUE credentials) {
299
303
  "grpc_call_set_credentials failed with %s (code=%d)",
300
304
  grpc_call_error_detail_of(err), err);
301
305
  }
306
+ rb_ivar_set(self, id_credentials, credentials);
302
307
  return Qnil;
303
308
  }
304
309
 
@@ -859,6 +864,7 @@ void Init_grpc_call() {
859
864
  id_cq = rb_intern("__cq");
860
865
  id_flags = rb_intern("__flags");
861
866
  id_input_md = rb_intern("__input_md");
867
+ id_credentials = rb_intern("__credentials");
862
868
 
863
869
  /* Ids used in constructing the batch result. */
864
870
  sym_send_message = ID2SYM(rb_intern("send_message"));
@@ -50,9 +50,9 @@
50
50
  * grpc_call_credentials */
51
51
  static VALUE grpc_rb_cCallCredentials = Qnil;
52
52
 
53
- /* grpc_rb_call_credentials wraps a grpc_call_credentials. It provides a peer
54
- * ruby object, 'mark' to minimize copying when a credential is created from
55
- * ruby. */
53
+ /* grpc_rb_call_credentials wraps a grpc_call_credentials. It provides a mark
54
+ * object that is used to hold references to any objects used to create the
55
+ * credentials. */
56
56
  typedef struct grpc_rb_call_credentials {
57
57
  /* Holder of ruby objects involved in contructing the credentials */
58
58
  VALUE mark;
@@ -146,13 +146,8 @@ static void grpc_rb_call_credentials_free(void *p) {
146
146
  return;
147
147
  }
148
148
  wrapper = (grpc_rb_call_credentials *)p;
149
-
150
- /* Delete the wrapped object if the mark object is Qnil, which indicates that
151
- * no other object is the actual owner. */
152
- if (wrapper->wrapped != NULL && wrapper->mark == Qnil) {
153
- grpc_call_credentials_release(wrapper->wrapped);
154
- wrapper->wrapped = NULL;
155
- }
149
+ grpc_call_credentials_release(wrapper->wrapped);
150
+ wrapper->wrapped = NULL;
156
151
 
157
152
  xfree(p);
158
153
  }
@@ -164,8 +159,6 @@ static void grpc_rb_call_credentials_mark(void *p) {
164
159
  return;
165
160
  }
166
161
  wrapper = (grpc_rb_call_credentials *)p;
167
-
168
- /* If it's not already cleaned up, mark the mark object */
169
162
  if (wrapper->mark != Qnil) {
170
163
  rb_gc_mark(wrapper->mark);
171
164
  }
@@ -194,7 +187,7 @@ static VALUE grpc_rb_call_credentials_alloc(VALUE cls) {
194
187
  /* Creates a wrapping object for a given call credentials. This should only be
195
188
  * called with grpc_call_credentials objects that are not already associated
196
189
  * with any Ruby object */
197
- VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c) {
190
+ VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c, VALUE mark) {
198
191
  VALUE rb_wrapper;
199
192
  grpc_rb_call_credentials *wrapper;
200
193
  if (c == NULL) {
@@ -204,6 +197,7 @@ VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c) {
204
197
  TypedData_Get_Struct(rb_wrapper, grpc_rb_call_credentials,
205
198
  &grpc_rb_call_credentials_data_type, wrapper);
206
199
  wrapper->wrapped = c;
200
+ wrapper->mark = mark;
207
201
  return rb_wrapper;
208
202
  }
209
203
 
@@ -267,6 +261,7 @@ static VALUE grpc_rb_call_credentials_init(VALUE self, VALUE proc) {
267
261
  return Qnil;
268
262
  }
269
263
 
264
+ wrapper->mark = proc;
270
265
  wrapper->wrapped = creds;
271
266
  rb_ivar_set(self, id_callback, proc);
272
267
 
@@ -277,15 +272,18 @@ static VALUE grpc_rb_call_credentials_compose(int argc, VALUE *argv,
277
272
  VALUE self) {
278
273
  grpc_call_credentials *creds;
279
274
  grpc_call_credentials *other;
275
+ VALUE mark;
280
276
  if (argc == 0) {
281
277
  return self;
282
278
  }
279
+ mark = rb_ary_new();
283
280
  creds = grpc_rb_get_wrapped_call_credentials(self);
284
281
  for (int i = 0; i < argc; i++) {
282
+ rb_ary_push(mark, argv[i]);
285
283
  other = grpc_rb_get_wrapped_call_credentials(argv[i]);
286
284
  creds = grpc_composite_call_credentials_create(creds, other, NULL);
287
285
  }
288
- return grpc_rb_wrap_call_credentials(creds);
286
+ return grpc_rb_wrap_call_credentials(creds, mark);
289
287
  }
290
288
 
291
289
  void Init_grpc_call_credentials() {
@@ -70,11 +70,10 @@ static VALUE grpc_rb_cChannel = Qnil;
70
70
  /* Used during the conversion of a hash to channel args during channel setup */
71
71
  static VALUE grpc_rb_cChannelArgs;
72
72
 
73
- /* grpc_rb_channel wraps a grpc_channel. It provides a peer ruby object,
74
- * 'mark' to minimize copying when a channel is created from ruby. */
73
+ /* grpc_rb_channel wraps a grpc_channel. */
75
74
  typedef struct grpc_rb_channel {
76
- /* Holder of ruby objects involved in constructing the channel */
77
- VALUE mark;
75
+ VALUE credentials;
76
+
78
77
  /* The actual channel */
79
78
  grpc_channel *wrapped;
80
79
  } grpc_rb_channel;
@@ -87,13 +86,8 @@ static void grpc_rb_channel_free(void *p) {
87
86
  };
88
87
  ch = (grpc_rb_channel *)p;
89
88
 
90
- /* Deletes the wrapped object if the mark object is Qnil, which indicates
91
- * that no other object is the actual owner. */
92
- if (ch->wrapped != NULL && ch->mark == Qnil) {
89
+ if (ch->wrapped != NULL) {
93
90
  grpc_channel_destroy(ch->wrapped);
94
- rb_warning("channel gc: destroyed the c channel");
95
- } else {
96
- rb_warning("channel gc: did not destroy the c channel");
97
91
  }
98
92
 
99
93
  xfree(p);
@@ -106,8 +100,8 @@ static void grpc_rb_channel_mark(void *p) {
106
100
  return;
107
101
  }
108
102
  channel = (grpc_rb_channel *)p;
109
- if (channel->mark != Qnil) {
110
- rb_gc_mark(channel->mark);
103
+ if (channel->credentials != Qnil) {
104
+ rb_gc_mark(channel->credentials);
111
105
  }
112
106
  }
113
107
 
@@ -125,7 +119,7 @@ static rb_data_type_t grpc_channel_data_type = {
125
119
  static VALUE grpc_rb_channel_alloc(VALUE cls) {
126
120
  grpc_rb_channel *wrapper = ALLOC(grpc_rb_channel);
127
121
  wrapper->wrapped = NULL;
128
- wrapper->mark = Qnil;
122
+ wrapper->credentials = Qnil;
129
123
  return TypedData_Wrap_Struct(cls, &grpc_channel_data_type, wrapper);
130
124
  }
131
125
 
@@ -162,6 +156,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
162
156
  }
163
157
  ch = grpc_insecure_channel_create(target_chars, &args, NULL);
164
158
  } else {
159
+ wrapper->credentials = credentials;
165
160
  creds = grpc_rb_get_wrapped_channel_credentials(credentials);
166
161
  ch = grpc_secure_channel_create(creds, target_chars, &args, NULL);
167
162
  }
@@ -330,7 +325,6 @@ static VALUE grpc_rb_channel_destroy(VALUE self) {
330
325
  if (ch != NULL) {
331
326
  grpc_channel_destroy(ch);
332
327
  wrapper->wrapped = NULL;
333
- wrapper->mark = Qnil;
334
328
  }
335
329
 
336
330
  return Qnil;
@@ -49,8 +49,8 @@
49
49
  static VALUE grpc_rb_cChannelCredentials = Qnil;
50
50
 
51
51
  /* grpc_rb_channel_credentials wraps a grpc_channel_credentials. It provides a
52
- * peer ruby object, 'mark' to minimize copying when a credential is
53
- * created from ruby. */
52
+ * mark object that is used to hold references to any objects used to create
53
+ * the credentials. */
54
54
  typedef struct grpc_rb_channel_credentials {
55
55
  /* Holder of ruby objects involved in constructing the credentials */
56
56
  VALUE mark;
@@ -66,13 +66,8 @@ static void grpc_rb_channel_credentials_free(void *p) {
66
66
  return;
67
67
  };
68
68
  wrapper = (grpc_rb_channel_credentials *)p;
69
-
70
- /* Delete the wrapped object if the mark object is Qnil, which indicates that
71
- * no other object is the actual owner. */
72
- if (wrapper->wrapped != NULL && wrapper->mark == Qnil) {
73
- grpc_channel_credentials_release(wrapper->wrapped);
74
- wrapper->wrapped = NULL;
75
- }
69
+ grpc_channel_credentials_release(wrapper->wrapped);
70
+ wrapper->wrapped = NULL;
76
71
 
77
72
  xfree(p);
78
73
  }
@@ -85,7 +80,6 @@ static void grpc_rb_channel_credentials_mark(void *p) {
85
80
  }
86
81
  wrapper = (grpc_rb_channel_credentials *)p;
87
82
 
88
- /* If it's not already cleaned up, mark the mark object */
89
83
  if (wrapper->mark != Qnil) {
90
84
  rb_gc_mark(wrapper->mark);
91
85
  }
@@ -114,7 +108,7 @@ static VALUE grpc_rb_channel_credentials_alloc(VALUE cls) {
114
108
  /* Creates a wrapping object for a given channel credentials. This should only
115
109
  * be called with grpc_channel_credentials objects that are not already
116
110
  * associated with any Ruby object. */
117
- VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c) {
111
+ VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c, VALUE mark) {
118
112
  VALUE rb_wrapper;
119
113
  grpc_rb_channel_credentials *wrapper;
120
114
  if (c == NULL) {
@@ -124,6 +118,7 @@ VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c) {
124
118
  TypedData_Get_Struct(rb_wrapper, grpc_rb_channel_credentials,
125
119
  &grpc_rb_channel_credentials_data_type, wrapper);
126
120
  wrapper->wrapped = c;
121
+ wrapper->mark = mark;
127
122
  return rb_wrapper;
128
123
  }
129
124
 
@@ -222,11 +217,15 @@ static VALUE grpc_rb_channel_credentials_compose(int argc, VALUE *argv,
222
217
  VALUE self) {
223
218
  grpc_channel_credentials *creds;
224
219
  grpc_call_credentials *other;
220
+ VALUE mark;
225
221
  if (argc == 0) {
226
222
  return self;
227
223
  }
224
+ mark = rb_ary_new();
225
+ rb_ary_push(mark, self);
228
226
  creds = grpc_rb_get_wrapped_channel_credentials(self);
229
227
  for (int i = 0; i < argc; i++) {
228
+ rb_ary_push(mark, argv[i]);
230
229
  other = grpc_rb_get_wrapped_call_credentials(argv[i]);
231
230
  creds = grpc_composite_channel_credentials_create(creds, other, NULL);
232
231
  if (creds == NULL) {
@@ -234,7 +233,7 @@ static VALUE grpc_rb_channel_credentials_compose(int argc, VALUE *argv,
234
233
  "Failed to compose channel and call credentials");
235
234
  }
236
235
  }
237
- return grpc_rb_wrap_channel_credentials(creds);
236
+ return grpc_rb_wrap_channel_credentials(creds, mark);
238
237
  }
239
238
 
240
239
  void Init_grpc_channel_credentials() {
@@ -269,20 +269,9 @@ static void Init_grpc_time_consts() {
269
269
  id_tv_nsec = rb_intern("tv_nsec");
270
270
  }
271
271
 
272
- /*
273
- TODO: find an alternative to ruby_vm_at_exit that is ok in Ruby 2.0 where
274
- RUBY_TYPED_FREE_IMMEDIATELY is not defined.
275
-
276
- At the moment, registering a function using ruby_vm_at_exit segfaults in Ruby
277
- 2.0. This is not an issue with the gRPC handler. More likely, this was an
278
- in issue with 2.0 that got resolved in 2.1 and has not been backported.
279
- */
280
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
281
- static void grpc_rb_shutdown(ruby_vm_t *vm) {
282
- (void)vm;
272
+ static void grpc_rb_shutdown(void) {
283
273
  grpc_shutdown();
284
274
  }
285
- #endif
286
275
 
287
276
  /* Initialize the GRPC module structs */
288
277
 
@@ -300,18 +289,30 @@ VALUE sym_code = Qundef;
300
289
  VALUE sym_details = Qundef;
301
290
  VALUE sym_metadata = Qundef;
302
291
 
292
+ static gpr_once g_once_init = GPR_ONCE_INIT;
293
+
294
+ static void grpc_ruby_once_init() {
295
+ grpc_init();
296
+ atexit(grpc_rb_shutdown);
297
+ }
298
+
303
299
  void Init_grpc_c() {
304
300
  if (!grpc_rb_load_core()) {
305
301
  rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
306
302
  return;
307
303
  }
308
304
 
309
- grpc_init();
310
-
311
- /* TODO: find alternative to ruby_vm_at_exit that is ok in Ruby 2.0 */
312
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
313
- ruby_vm_at_exit(grpc_rb_shutdown);
314
- #endif
305
+ /* ruby_vm_at_exit doesn't seem to be working. It would crash once every
306
+ * blue moon, and some users are getting it repeatedly. See the discussions
307
+ * - https://github.com/grpc/grpc/pull/5337
308
+ * - https://bugs.ruby-lang.org/issues/12095
309
+ *
310
+ * In order to still be able to handle the (unlikely) situation where the
311
+ * extension is loaded by a first Ruby VM that is subsequently destroyed,
312
+ * then loaded again by another VM within the same process, we need to
313
+ * schedule our initialization and destruction only once.
314
+ */
315
+ gpr_once_init(&g_once_init, grpc_ruby_once_init);
315
316
 
316
317
  grpc_rb_mGRPC = rb_define_module("GRPC");
317
318
  grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
@@ -137,6 +137,7 @@ grpc_auth_context_add_cstring_property_type grpc_auth_context_add_cstring_proper
137
137
  grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_peer_identity_property_name_import;
138
138
  grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
139
139
  grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
140
+ grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
140
141
  grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
141
142
  grpc_call_credentials_release_type grpc_call_credentials_release_import;
142
143
  grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import;
@@ -219,6 +220,7 @@ gpr_event_get_type gpr_event_get_import;
219
220
  gpr_event_wait_type gpr_event_wait_import;
220
221
  gpr_ref_init_type gpr_ref_init_import;
221
222
  gpr_ref_type gpr_ref_import;
223
+ gpr_ref_non_zero_type gpr_ref_non_zero_import;
222
224
  gpr_refn_type gpr_refn_import;
223
225
  gpr_unref_type gpr_unref_import;
224
226
  gpr_stats_init_type gpr_stats_init_import;
@@ -397,6 +399,7 @@ void grpc_rb_load_imports(HMODULE library) {
397
399
  grpc_auth_context_set_peer_identity_property_name_import = (grpc_auth_context_set_peer_identity_property_name_type) GetProcAddress(library, "grpc_auth_context_set_peer_identity_property_name");
398
400
  grpc_channel_credentials_release_import = (grpc_channel_credentials_release_type) GetProcAddress(library, "grpc_channel_credentials_release");
399
401
  grpc_google_default_credentials_create_import = (grpc_google_default_credentials_create_type) GetProcAddress(library, "grpc_google_default_credentials_create");
402
+ grpc_set_ssl_roots_override_callback_import = (grpc_set_ssl_roots_override_callback_type) GetProcAddress(library, "grpc_set_ssl_roots_override_callback");
400
403
  grpc_ssl_credentials_create_import = (grpc_ssl_credentials_create_type) GetProcAddress(library, "grpc_ssl_credentials_create");
401
404
  grpc_call_credentials_release_import = (grpc_call_credentials_release_type) GetProcAddress(library, "grpc_call_credentials_release");
402
405
  grpc_composite_channel_credentials_create_import = (grpc_composite_channel_credentials_create_type) GetProcAddress(library, "grpc_composite_channel_credentials_create");
@@ -479,6 +482,7 @@ void grpc_rb_load_imports(HMODULE library) {
479
482
  gpr_event_wait_import = (gpr_event_wait_type) GetProcAddress(library, "gpr_event_wait");
480
483
  gpr_ref_init_import = (gpr_ref_init_type) GetProcAddress(library, "gpr_ref_init");
481
484
  gpr_ref_import = (gpr_ref_type) GetProcAddress(library, "gpr_ref");
485
+ gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero");
482
486
  gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn");
483
487
  gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref");
484
488
  gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init");
@@ -91,10 +91,10 @@ extern census_context_next_tag_type census_context_next_tag_import;
91
91
  typedef int(*census_context_get_tag_type)(const census_context *context, const char *key, census_tag *tag);
92
92
  extern census_context_get_tag_type census_context_get_tag_import;
93
93
  #define census_context_get_tag census_context_get_tag_import
94
- typedef char *(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size, size_t *print_buf_size, size_t *bin_buf_size);
94
+ typedef size_t(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size);
95
95
  extern census_context_encode_type census_context_encode_import;
96
96
  #define census_context_encode census_context_encode_import
97
- typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size, const char *bin_buffer, size_t bin_size);
97
+ typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size);
98
98
  extern census_context_decode_type census_context_decode_import;
99
99
  #define census_context_decode census_context_decode_import
100
100
  typedef int(*census_trace_mask_type)(const census_context *context);
@@ -361,6 +361,9 @@ extern grpc_channel_credentials_release_type grpc_channel_credentials_release_im
361
361
  typedef grpc_channel_credentials *(*grpc_google_default_credentials_create_type)(void);
362
362
  extern grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
363
363
  #define grpc_google_default_credentials_create grpc_google_default_credentials_create_import
364
+ typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
365
+ extern grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
366
+ #define grpc_set_ssl_roots_override_callback grpc_set_ssl_roots_override_callback_import
364
367
  typedef grpc_channel_credentials *(*grpc_ssl_credentials_create_type)(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved);
365
368
  extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
366
369
  #define grpc_ssl_credentials_create grpc_ssl_credentials_create_import
@@ -607,6 +610,9 @@ extern gpr_ref_init_type gpr_ref_init_import;
607
610
  typedef void(*gpr_ref_type)(gpr_refcount *r);
608
611
  extern gpr_ref_type gpr_ref_import;
609
612
  #define gpr_ref gpr_ref_import
613
+ typedef void(*gpr_ref_non_zero_type)(gpr_refcount *r);
614
+ extern gpr_ref_non_zero_type gpr_ref_non_zero_import;
615
+ #define gpr_ref_non_zero gpr_ref_non_zero_import
610
616
  typedef void(*gpr_refn_type)(gpr_refcount *r, int n);
611
617
  extern gpr_refn_type gpr_refn_import;
612
618
  #define gpr_refn gpr_refn_import
@@ -1,4 +1,4 @@
1
- # Copyright 2015, Google Inc.
1
+ # Copyright 2015-2016, Google Inc.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
27
27
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
- require 'grpc'
30
+ require 'grpc/grpc'
31
31
 
32
32
  # GRPC contains the General RPC module.
33
33
  module GRPC
@@ -1,4 +1,4 @@
1
- # Copyright 2015, Google Inc.
1
+ # Copyright 2015-2016, Google Inc.
2
2
  # All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
27
27
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
- require 'grpc'
30
+ require 'grpc/grpc'
31
31
 
32
32
  # GRPC contains the General RPC module.
33
33
  module GRPC
@@ -107,7 +107,9 @@ module GRPC
107
107
 
108
108
  # Starts running the jobs in the thread pool.
109
109
  def start
110
- fail 'already stopped' if @stopped
110
+ @stop_mutex.synchronize do
111
+ fail 'already stopped' if @stopped
112
+ end
111
113
  until @workers.size == @size.to_i
112
114
  next_thread = Thread.new do
113
115
  catch(:exit) do # allows { throw :exit } to kill a thread
@@ -264,10 +266,10 @@ module GRPC
264
266
  @pool = Pool.new(@pool_size)
265
267
  @run_cond = ConditionVariable.new
266
268
  @run_mutex = Mutex.new
267
- @running = false
269
+ # running_state can take 4 values: :not_started, :running, :stopping, and
270
+ # :stopped. State transitions can only proceed in that order.
271
+ @running_state = :not_started
268
272
  @server = RpcServer.setup_srv(server_override, @cq, **kw)
269
- @stopped = false
270
- @stop_mutex = Mutex.new
271
273
  end
272
274
 
273
275
  # stops a running server
@@ -275,27 +277,42 @@ module GRPC
275
277
  # the call has no impact if the server is already stopped, otherwise
276
278
  # server's current call loop is it's last.
277
279
  def stop
278
- return unless @running
279
- @stop_mutex.synchronize do
280
- @stopped = true
280
+ @run_mutex.synchronize do
281
+ fail 'Cannot stop before starting' if @running_state == :not_started
282
+ return if @running_state != :running
283
+ transition_running_state(:stopping)
281
284
  end
282
285
  deadline = from_relative_time(@poll_period)
283
- return if @server.close(@cq, deadline)
284
- deadline = from_relative_time(@poll_period)
285
286
  @server.close(@cq, deadline)
286
287
  @pool.stop
287
288
  end
288
289
 
289
- # determines if the server has been stopped
290
- def stopped?
291
- @stop_mutex.synchronize do
292
- return @stopped
290
+ def running_state
291
+ @run_mutex.synchronize do
292
+ return @running_state
293
+ end
294
+ end
295
+
296
+ # Can only be called while holding @run_mutex
297
+ def transition_running_state(target_state)
298
+ state_transitions = {
299
+ not_started: :running,
300
+ running: :stopping,
301
+ stopping: :stopped
302
+ }
303
+ if state_transitions[@running_state] == target_state
304
+ @running_state = target_state
305
+ else
306
+ fail "Bad server state transition: #{@running_state}->#{target_state}"
293
307
  end
294
308
  end
295
309
 
296
- # determines if the server is currently running
297
310
  def running?
298
- @running
311
+ running_state == :running
312
+ end
313
+
314
+ def stopped?
315
+ running_state == :stopped
299
316
  end
300
317
 
301
318
  # Is called from other threads to wait for #run to start up the server.
@@ -304,13 +321,11 @@ module GRPC
304
321
  #
305
322
  # @param timeout [Numeric] number of seconds to wait
306
323
  # @result [true, false] true if the server is running, false otherwise
307
- def wait_till_running(timeout = 0.1)
308
- end_time, sleep_period = Time.now + timeout, (1.0 * timeout) / 100
309
- while Time.now < end_time
310
- @run_mutex.synchronize { @run_cond.wait(@run_mutex) } unless running?
311
- sleep(sleep_period)
324
+ def wait_till_running(timeout = nil)
325
+ @run_mutex.synchronize do
326
+ @run_cond.wait(@run_mutex, timeout) if @running_state == :not_started
327
+ return @running_state == :running
312
328
  end
313
- running?
314
329
  end
315
330
 
316
331
  # Runs the server in its own thread, then waits for signal INT or TERM on
@@ -360,11 +375,14 @@ module GRPC
360
375
  # @param service [Object|Class] a service class or object as described
361
376
  # above
362
377
  def handle(service)
363
- fail 'cannot add services if the server is running' if running?
364
- fail 'cannot add services if the server is stopped' if stopped?
365
- cls = service.is_a?(Class) ? service : service.class
366
- assert_valid_service_class(cls)
367
- add_rpc_descs_for(service)
378
+ @run_mutex.synchronize do
379
+ unless @running_state == :not_started
380
+ fail 'cannot add services if the server has been started'
381
+ end
382
+ cls = service.is_a?(Class) ? service : service.class
383
+ assert_valid_service_class(cls)
384
+ add_rpc_descs_for(service)
385
+ end
368
386
  end
369
387
 
370
388
  # runs the server
@@ -375,16 +393,13 @@ module GRPC
375
393
  # - #running? returns true after this is called, until #stop cause the
376
394
  # the server to stop.
377
395
  def run
378
- if rpc_descs.size.zero?
379
- GRPC.logger.warn('did not run as no services were present')
380
- return
381
- end
382
396
  @run_mutex.synchronize do
383
- @running = true
384
- @run_cond.signal
397
+ fail 'cannot run without registering services' if rpc_descs.size.zero?
398
+ @pool.start
399
+ @server.start
400
+ transition_running_state(:running)
401
+ @run_cond.broadcast
385
402
  end
386
- @pool.start
387
- @server.start
388
403
  loop_handle_server_calls
389
404
  end
390
405
 
@@ -413,9 +428,9 @@ module GRPC
413
428
 
414
429
  # handles calls to the server
415
430
  def loop_handle_server_calls
416
- fail 'not running' unless @running
431
+ fail 'not started' if running_state == :not_started
417
432
  loop_tag = Object.new
418
- until stopped?
433
+ while running_state == :running
419
434
  begin
420
435
  an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
421
436
  break if (!an_rpc.nil?) && an_rpc.call.nil?
@@ -430,11 +445,14 @@ module GRPC
430
445
  rescue Core::CallError, RuntimeError => e
431
446
  # these might happen for various reasonse. The correct behaviour of
432
447
  # the server is to log them and continue, if it's not shutting down.
433
- GRPC.logger.warn("server call failed: #{e}") unless stopped?
448
+ if running_state == :running
449
+ GRPC.logger.warn("server call failed: #{e}")
450
+ end
434
451
  next
435
452
  end
436
453
  end
437
- @running = false
454
+ # @running_state should be :stopping here
455
+ @run_mutex.synchronize { transition_running_state(:stopped) }
438
456
  GRPC.logger.info("stopped: #{self}")
439
457
  end
440
458
 
@@ -484,9 +502,10 @@ module GRPC
484
502
  cls.assert_rpc_descs_have_methods
485
503
  end
486
504
 
505
+ # This should be called while holding @run_mutex
487
506
  def add_rpc_descs_for(service)
488
507
  cls = service.is_a?(Class) ? service : service.class
489
- specs, handlers = rpc_descs, rpc_handlers
508
+ specs, handlers = (@rpc_descs ||= {}), (@rpc_handlers ||= {})
490
509
  cls.rpc_descs.each_pair do |name, spec|
491
510
  route = "/#{cls.service_name}/#{name}".to_sym
492
511
  fail "already registered: rpc #{route} from #{spec}" if specs.key? route