grpc 1.42.0.pre1-arm64-darwin → 1.60.0.pre1-arm64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/grpc_c.64-ucrt.ruby +0 -0
- data/src/ruby/bin/math_pb.rb +24 -18
- data/src/ruby/ext/grpc/ext-export-truffleruby-with-ruby-abi-version.clang +2 -0
- data/src/ruby/ext/grpc/ext-export-truffleruby-with-ruby-abi-version.gcc +7 -0
- data/src/ruby/ext/grpc/ext-export-with-ruby-abi-version.clang +2 -0
- data/src/ruby/ext/grpc/ext-export-with-ruby-abi-version.gcc +7 -0
- data/src/ruby/ext/grpc/ext-export.gcc +1 -1
- data/src/ruby/ext/grpc/extconf.rb +174 -27
- data/src/ruby/ext/grpc/rb_call.c +63 -39
- data/src/ruby/ext/grpc/rb_call_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_channel.c +113 -84
- data/src/ruby/ext/grpc/rb_channel.h +1 -0
- data/src/ruby/ext/grpc/rb_channel_args.c +19 -2
- data/src/ruby/ext/grpc/rb_channel_args.h +4 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_compression_options.c +1 -2
- data/src/ruby/ext/grpc/rb_event_thread.c +22 -6
- data/src/ruby/ext/grpc/rb_event_thread.h +1 -0
- data/src/ruby/ext/grpc/rb_grpc.c +193 -30
- data/src/ruby/ext/grpc/rb_grpc.h +8 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +70 -72
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +108 -111
- data/src/ruby/ext/grpc/rb_loader.c +6 -2
- data/src/ruby/ext/grpc/rb_server.c +69 -49
- data/src/ruby/ext/grpc/rb_server_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_xds_server_credentials.c +0 -1
- data/src/ruby/lib/grpc/2.7/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/3.0/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/3.1/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/3.2/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/errors.rb +1 -1
- data/src/ruby/lib/grpc/generic/active_call.rb +16 -15
- data/src/ruby/lib/grpc/generic/bidi_call.rb +4 -0
- data/src/ruby/lib/grpc/grpc.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/generate_proto_ruby.sh +1 -6
- data/src/ruby/pb/grpc/health/v1/health_pb.rb +24 -13
- data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +24 -3
- data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +34 -108
- data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +27 -3
- data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +22 -0
- data/src/ruby/pb/test/client.rb +16 -0
- data/src/ruby/spec/channel_spec.rb +5 -43
- data/src/ruby/spec/client_server_spec.rb +20 -8
- data/src/ruby/spec/generic/active_call_spec.rb +12 -3
- data/src/ruby/spec/generic/client_stub_spec.rb +23 -23
- data/src/ruby/spec/generic/rpc_server_spec.rb +3 -3
- data/src/ruby/spec/generic/server_interceptors_spec.rb +1 -1
- data/src/ruby/spec/user_agent_spec.rb +1 -1
- metadata +59 -58
- data/src/ruby/lib/grpc/2.4/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.5/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.6/grpc_c.bundle +0 -0
- /data/{grpc_c.32.ruby → grpc_c.32-msvcrt.ruby} +0 -0
- /data/{grpc_c.64.ruby → grpc_c.64-msvcrt.ruby} +0 -0
@@ -47,6 +47,9 @@ static ID id_channel;
|
|
47
47
|
* GCed before the channel */
|
48
48
|
static ID id_target;
|
49
49
|
|
50
|
+
/* hidden ivar that synchronizes post-fork channel re-creation */
|
51
|
+
static ID id_channel_recreation_mu;
|
52
|
+
|
50
53
|
/* id_insecure_channel is used to indicate that a channel is insecure */
|
51
54
|
static VALUE id_insecure_channel;
|
52
55
|
|
@@ -67,7 +70,7 @@ typedef struct bg_watched_channel {
|
|
67
70
|
/* grpc_rb_channel wraps a grpc_channel. */
|
68
71
|
typedef struct grpc_rb_channel {
|
69
72
|
VALUE credentials;
|
70
|
-
|
73
|
+
grpc_channel_args args;
|
71
74
|
/* The actual channel (protected in a wrapper to tell when it's safe to
|
72
75
|
* destroy) */
|
73
76
|
bg_watched_channel* bg_wrapped;
|
@@ -94,8 +97,6 @@ static bg_watched_channel* bg_watched_channel_list_head = NULL;
|
|
94
97
|
|
95
98
|
static void grpc_rb_channel_try_register_connection_polling(
|
96
99
|
bg_watched_channel* bg);
|
97
|
-
static void* wait_until_channel_polling_thread_started_no_gil(void*);
|
98
|
-
static void wait_until_channel_polling_thread_started_unblocking_func(void*);
|
99
100
|
static void* channel_init_try_register_connection_polling_without_gil(
|
100
101
|
void* arg);
|
101
102
|
|
@@ -104,11 +105,12 @@ typedef struct channel_init_try_register_stack {
|
|
104
105
|
grpc_rb_channel* wrapper;
|
105
106
|
} channel_init_try_register_stack;
|
106
107
|
|
107
|
-
static grpc_completion_queue*
|
108
|
+
static grpc_completion_queue* g_channel_polling_cq;
|
108
109
|
static gpr_mu global_connection_polling_mu;
|
109
110
|
static gpr_cv global_connection_polling_cv;
|
110
|
-
static int
|
111
|
-
static
|
111
|
+
static int g_abort_channel_polling = 0;
|
112
|
+
static gpr_once g_once_init = GPR_ONCE_INIT;
|
113
|
+
static VALUE g_channel_polling_thread = Qnil;
|
112
114
|
|
113
115
|
static int bg_watched_channel_list_lookup(bg_watched_channel* bg);
|
114
116
|
static bg_watched_channel* bg_watched_channel_list_create_and_add(
|
@@ -158,16 +160,13 @@ static void grpc_rb_channel_free_internal(void* p) {
|
|
158
160
|
* and we can count on this thread to not be interrupted or
|
159
161
|
* yield the gil. */
|
160
162
|
grpc_rb_channel_safe_destroy(ch->bg_wrapped);
|
161
|
-
ch->
|
163
|
+
grpc_rb_channel_args_destroy(&ch->args);
|
162
164
|
}
|
163
165
|
xfree(p);
|
164
166
|
}
|
165
167
|
|
166
168
|
/* Destroys Channel instances. */
|
167
|
-
static void grpc_rb_channel_free(void* p) {
|
168
|
-
grpc_rb_channel_free_internal(p);
|
169
|
-
grpc_ruby_shutdown();
|
170
|
-
}
|
169
|
+
static void grpc_rb_channel_free(void* p) { grpc_rb_channel_free_internal(p); }
|
171
170
|
|
172
171
|
/* Protects the mark object from GC */
|
173
172
|
static void grpc_rb_channel_mark(void* p) {
|
@@ -199,6 +198,7 @@ static VALUE grpc_rb_channel_alloc(VALUE cls) {
|
|
199
198
|
grpc_rb_channel* wrapper = ALLOC(grpc_rb_channel);
|
200
199
|
wrapper->bg_wrapped = NULL;
|
201
200
|
wrapper->credentials = Qnil;
|
201
|
+
MEMZERO(&wrapper->args, grpc_channel_args, 1);
|
202
202
|
return TypedData_Wrap_Struct(cls, &grpc_channel_data_type, wrapper);
|
203
203
|
}
|
204
204
|
|
@@ -218,31 +218,25 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
|
|
218
218
|
grpc_channel* ch = NULL;
|
219
219
|
grpc_channel_credentials* creds = NULL;
|
220
220
|
char* target_chars = NULL;
|
221
|
-
grpc_channel_args args;
|
222
221
|
channel_init_try_register_stack stack;
|
223
|
-
int stop_waiting_for_thread_start = 0;
|
224
|
-
MEMZERO(&args, grpc_channel_args, 1);
|
225
222
|
|
226
223
|
grpc_ruby_fork_guard();
|
227
|
-
rb_thread_call_without_gvl(
|
228
|
-
wait_until_channel_polling_thread_started_no_gil,
|
229
|
-
&stop_waiting_for_thread_start,
|
230
|
-
wait_until_channel_polling_thread_started_unblocking_func,
|
231
|
-
&stop_waiting_for_thread_start);
|
232
|
-
|
233
224
|
/* "3" == 3 mandatory args */
|
234
225
|
rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials);
|
235
226
|
|
236
227
|
TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
|
237
228
|
target_chars = StringValueCStr(target);
|
238
|
-
grpc_rb_hash_convert_to_channel_args(channel_args, &args);
|
229
|
+
grpc_rb_hash_convert_to_channel_args(channel_args, &wrapper->args);
|
239
230
|
if (TYPE(credentials) == T_SYMBOL) {
|
240
231
|
if (id_insecure_channel != SYM2ID(credentials)) {
|
241
232
|
rb_raise(rb_eTypeError,
|
242
233
|
"bad creds symbol, want :this_channel_is_insecure");
|
243
234
|
return Qnil;
|
244
235
|
}
|
245
|
-
|
236
|
+
grpc_channel_credentials* insecure_creds =
|
237
|
+
grpc_insecure_credentials_create();
|
238
|
+
ch = grpc_channel_create(target_chars, insecure_creds, &wrapper->args);
|
239
|
+
grpc_channel_credentials_release(insecure_creds);
|
246
240
|
} else {
|
247
241
|
wrapper->credentials = credentials;
|
248
242
|
if (grpc_rb_is_channel_credentials(credentials)) {
|
@@ -254,7 +248,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
|
|
254
248
|
"bad creds, want ChannelCredentials or XdsChannelCredentials");
|
255
249
|
return Qnil;
|
256
250
|
}
|
257
|
-
ch =
|
251
|
+
ch = grpc_channel_create(target_chars, creds, &wrapper->args);
|
258
252
|
}
|
259
253
|
|
260
254
|
GPR_ASSERT(ch);
|
@@ -263,16 +257,13 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
|
|
263
257
|
rb_thread_call_without_gvl(
|
264
258
|
channel_init_try_register_connection_polling_without_gil, &stack, NULL,
|
265
259
|
NULL);
|
266
|
-
|
267
|
-
if (args.args != NULL) {
|
268
|
-
xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */
|
269
|
-
}
|
270
260
|
if (ch == NULL) {
|
271
261
|
rb_raise(rb_eRuntimeError, "could not create an rpc channel to target:%s",
|
272
262
|
target_chars);
|
273
263
|
return Qnil;
|
274
264
|
}
|
275
265
|
rb_ivar_set(self, id_target, target);
|
266
|
+
rb_ivar_set(self, id_channel_recreation_mu, rb_mutex_new());
|
276
267
|
return self;
|
277
268
|
}
|
278
269
|
|
@@ -286,7 +277,6 @@ static void* get_state_without_gil(void* arg) {
|
|
286
277
|
get_state_stack* stack = (get_state_stack*)arg;
|
287
278
|
|
288
279
|
gpr_mu_lock(&global_connection_polling_mu);
|
289
|
-
GPR_ASSERT(abort_channel_polling || channel_polling_thread_started);
|
290
280
|
if (stack->bg->channel_destroyed) {
|
291
281
|
stack->out = GRPC_CHANNEL_SHUTDOWN;
|
292
282
|
} else {
|
@@ -343,7 +333,7 @@ static void* wait_for_watch_state_op_complete_without_gvl(void* arg) {
|
|
343
333
|
gpr_mu_lock(&global_connection_polling_mu);
|
344
334
|
// it's unsafe to do a "watch" after "channel polling abort" because the cq
|
345
335
|
// has been shut down.
|
346
|
-
if (
|
336
|
+
if (g_abort_channel_polling || stack->bg_wrapped->channel_destroyed) {
|
347
337
|
gpr_mu_unlock(&global_connection_polling_mu);
|
348
338
|
return (void*)0;
|
349
339
|
}
|
@@ -351,7 +341,7 @@ static void* wait_for_watch_state_op_complete_without_gvl(void* arg) {
|
|
351
341
|
op->op_type = WATCH_STATE_API;
|
352
342
|
grpc_channel_watch_connectivity_state(stack->bg_wrapped->channel,
|
353
343
|
stack->last_state, stack->deadline,
|
354
|
-
|
344
|
+
g_channel_polling_cq, op);
|
355
345
|
|
356
346
|
while (!op->op.api_callback_args.called_back) {
|
357
347
|
gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu,
|
@@ -415,6 +405,51 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
|
|
415
405
|
return op_success ? Qtrue : Qfalse;
|
416
406
|
}
|
417
407
|
|
408
|
+
static void grpc_rb_channel_maybe_recreate_channel_after_fork(
|
409
|
+
grpc_rb_channel* wrapper, VALUE target) {
|
410
|
+
// TODO(apolcyn): maybe check if fork support is enabled here.
|
411
|
+
// The only way we can get bg->channel_destroyed without bg itself being
|
412
|
+
// NULL is if we destroyed the channel during GRPC::prefork.
|
413
|
+
bg_watched_channel* bg = wrapper->bg_wrapped;
|
414
|
+
if (bg->channel_destroyed) {
|
415
|
+
// There must be one ref at this point, held by the ruby-level channel
|
416
|
+
// object, drop this one here.
|
417
|
+
GPR_ASSERT(bg->refcount == 1);
|
418
|
+
rb_thread_call_without_gvl(channel_safe_destroy_without_gil, bg, NULL,
|
419
|
+
NULL);
|
420
|
+
// re-create C-core channel
|
421
|
+
const char* target_str = StringValueCStr(target);
|
422
|
+
grpc_channel* channel;
|
423
|
+
if (wrapper->credentials == Qnil) {
|
424
|
+
grpc_channel_credentials* insecure_creds =
|
425
|
+
grpc_insecure_credentials_create();
|
426
|
+
channel = grpc_channel_create(target_str, insecure_creds, &wrapper->args);
|
427
|
+
grpc_channel_credentials_release(insecure_creds);
|
428
|
+
} else {
|
429
|
+
grpc_channel_credentials* creds;
|
430
|
+
if (grpc_rb_is_channel_credentials(wrapper->credentials)) {
|
431
|
+
creds = grpc_rb_get_wrapped_channel_credentials(wrapper->credentials);
|
432
|
+
} else if (grpc_rb_is_xds_channel_credentials(wrapper->credentials)) {
|
433
|
+
creds =
|
434
|
+
grpc_rb_get_wrapped_xds_channel_credentials(wrapper->credentials);
|
435
|
+
} else {
|
436
|
+
rb_raise(rb_eTypeError,
|
437
|
+
"failed to re-create channel after fork: bad creds, want "
|
438
|
+
"ChannelCredentials or XdsChannelCredentials");
|
439
|
+
return;
|
440
|
+
}
|
441
|
+
channel = grpc_channel_create(target_str, creds, &wrapper->args);
|
442
|
+
}
|
443
|
+
// re-register with channel polling thread
|
444
|
+
channel_init_try_register_stack stack;
|
445
|
+
stack.channel = channel;
|
446
|
+
stack.wrapper = wrapper;
|
447
|
+
rb_thread_call_without_gvl(
|
448
|
+
channel_init_try_register_connection_polling_without_gil, &stack, NULL,
|
449
|
+
NULL);
|
450
|
+
}
|
451
|
+
}
|
452
|
+
|
418
453
|
/* Create a call given a grpc_channel, in order to call method. The request
|
419
454
|
is not sent until grpc_call_invoke is called. */
|
420
455
|
static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask,
|
@@ -449,6 +484,11 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask,
|
|
449
484
|
rb_raise(rb_eRuntimeError, "closed!");
|
450
485
|
return Qnil;
|
451
486
|
}
|
487
|
+
// TODO(apolcyn): only do this check if fork support is enabled
|
488
|
+
rb_mutex_lock(rb_ivar_get(self, id_channel_recreation_mu));
|
489
|
+
grpc_rb_channel_maybe_recreate_channel_after_fork(
|
490
|
+
wrapper, rb_ivar_get(self, id_target));
|
491
|
+
rb_mutex_unlock(rb_ivar_get(self, id_channel_recreation_mu));
|
452
492
|
|
453
493
|
cq = grpc_completion_queue_create_for_pluck(NULL);
|
454
494
|
method_slice =
|
@@ -578,19 +618,15 @@ static void grpc_rb_channel_try_register_connection_polling(
|
|
578
618
|
bg_watched_channel* bg) {
|
579
619
|
grpc_connectivity_state conn_state;
|
580
620
|
watch_state_op* op = NULL;
|
581
|
-
|
582
|
-
GPR_ASSERT(channel_polling_thread_started || abort_channel_polling);
|
583
|
-
|
584
621
|
if (bg->refcount == 0) {
|
585
622
|
GPR_ASSERT(bg->channel_destroyed);
|
586
623
|
bg_watched_channel_list_free_and_remove(bg);
|
587
624
|
return;
|
588
625
|
}
|
589
626
|
GPR_ASSERT(bg->refcount == 1);
|
590
|
-
if (bg->channel_destroyed ||
|
627
|
+
if (bg->channel_destroyed || g_abort_channel_polling) {
|
591
628
|
return;
|
592
629
|
}
|
593
|
-
|
594
630
|
conn_state = grpc_channel_check_connectivity_state(bg->channel, 0);
|
595
631
|
if (conn_state == GRPC_CHANNEL_SHUTDOWN) {
|
596
632
|
return;
|
@@ -598,13 +634,12 @@ static void grpc_rb_channel_try_register_connection_polling(
|
|
598
634
|
GPR_ASSERT(bg_watched_channel_list_lookup(bg));
|
599
635
|
// prevent bg from being free'd by GC while background thread is watching it
|
600
636
|
bg->refcount++;
|
601
|
-
|
602
637
|
op = gpr_zalloc(sizeof(watch_state_op));
|
603
638
|
op->op_type = CONTINUOUS_WATCH;
|
604
639
|
op->op.continuous_watch_callback_args.bg = bg;
|
605
640
|
grpc_channel_watch_connectivity_state(bg->channel, conn_state,
|
606
641
|
gpr_inf_future(GPR_CLOCK_REALTIME),
|
607
|
-
|
642
|
+
g_channel_polling_cq, op);
|
608
643
|
}
|
609
644
|
|
610
645
|
// Note this loop breaks out with a single call of
|
@@ -621,14 +656,12 @@ static void* run_poll_channels_loop_no_gil(void* arg) {
|
|
621
656
|
gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - begin");
|
622
657
|
|
623
658
|
gpr_mu_lock(&global_connection_polling_mu);
|
624
|
-
GPR_ASSERT(!channel_polling_thread_started);
|
625
|
-
channel_polling_thread_started = 1;
|
626
659
|
gpr_cv_broadcast(&global_connection_polling_cv);
|
627
660
|
gpr_mu_unlock(&global_connection_polling_mu);
|
628
661
|
|
629
662
|
for (;;) {
|
630
663
|
event = grpc_completion_queue_next(
|
631
|
-
|
664
|
+
g_channel_polling_cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
632
665
|
if (event.type == GRPC_QUEUE_SHUTDOWN) {
|
633
666
|
break;
|
634
667
|
}
|
@@ -649,7 +682,7 @@ static void* run_poll_channels_loop_no_gil(void* arg) {
|
|
649
682
|
}
|
650
683
|
gpr_mu_unlock(&global_connection_polling_mu);
|
651
684
|
}
|
652
|
-
grpc_completion_queue_destroy(
|
685
|
+
grpc_completion_queue_destroy(g_channel_polling_cq);
|
653
686
|
gpr_log(GPR_DEBUG,
|
654
687
|
"GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling "
|
655
688
|
"loop");
|
@@ -666,11 +699,11 @@ static void run_poll_channels_loop_unblocking_func(void* arg) {
|
|
666
699
|
"GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting "
|
667
700
|
"connection polling");
|
668
701
|
// early out after first time through
|
669
|
-
if (
|
702
|
+
if (g_abort_channel_polling) {
|
670
703
|
gpr_mu_unlock(&global_connection_polling_mu);
|
671
704
|
return;
|
672
705
|
}
|
673
|
-
|
706
|
+
g_abort_channel_polling = 1;
|
674
707
|
|
675
708
|
// force pending watches to end by switching to shutdown state
|
676
709
|
bg = bg_watched_channel_list_head;
|
@@ -682,7 +715,9 @@ static void run_poll_channels_loop_unblocking_func(void* arg) {
|
|
682
715
|
bg = bg->next;
|
683
716
|
}
|
684
717
|
|
685
|
-
|
718
|
+
gpr_log(GPR_DEBUG, "GRPC_RUBY: cq shutdown on global polling cq. pid: %d",
|
719
|
+
getpid());
|
720
|
+
grpc_completion_queue_shutdown(g_channel_polling_cq);
|
686
721
|
gpr_cv_broadcast(&global_connection_polling_cv);
|
687
722
|
gpr_mu_unlock(&global_connection_polling_mu);
|
688
723
|
gpr_log(GPR_DEBUG,
|
@@ -696,47 +731,25 @@ static VALUE run_poll_channels_loop(VALUE arg) {
|
|
696
731
|
gpr_log(
|
697
732
|
GPR_DEBUG,
|
698
733
|
"GRPC_RUBY: run_poll_channels_loop - create connection polling thread");
|
699
|
-
grpc_ruby_init();
|
700
734
|
rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL,
|
701
735
|
run_poll_channels_loop_unblocking_func, NULL);
|
702
|
-
grpc_ruby_shutdown();
|
703
736
|
return Qnil;
|
704
737
|
}
|
705
738
|
|
706
|
-
static void* wait_until_channel_polling_thread_started_no_gil(void* arg) {
|
707
|
-
int* stop_waiting = (int*)arg;
|
708
|
-
gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start");
|
709
|
-
gpr_mu_lock(&global_connection_polling_mu);
|
710
|
-
while (!channel_polling_thread_started && !abort_channel_polling &&
|
711
|
-
!*stop_waiting) {
|
712
|
-
gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu,
|
713
|
-
gpr_inf_future(GPR_CLOCK_REALTIME));
|
714
|
-
}
|
715
|
-
gpr_mu_unlock(&global_connection_polling_mu);
|
716
|
-
|
717
|
-
return NULL;
|
718
|
-
}
|
719
|
-
|
720
|
-
static void wait_until_channel_polling_thread_started_unblocking_func(
|
721
|
-
void* arg) {
|
722
|
-
int* stop_waiting = (int*)arg;
|
723
|
-
gpr_mu_lock(&global_connection_polling_mu);
|
724
|
-
gpr_log(GPR_DEBUG,
|
725
|
-
"GRPC_RUBY: interrupt wait for channel polling thread to start");
|
726
|
-
*stop_waiting = 1;
|
727
|
-
gpr_cv_broadcast(&global_connection_polling_cv);
|
728
|
-
gpr_mu_unlock(&global_connection_polling_mu);
|
729
|
-
}
|
730
|
-
|
731
739
|
static void* set_abort_channel_polling_without_gil(void* arg) {
|
732
740
|
(void)arg;
|
733
741
|
gpr_mu_lock(&global_connection_polling_mu);
|
734
|
-
|
742
|
+
g_abort_channel_polling = 1;
|
735
743
|
gpr_cv_broadcast(&global_connection_polling_cv);
|
736
744
|
gpr_mu_unlock(&global_connection_polling_mu);
|
737
745
|
return NULL;
|
738
746
|
}
|
739
747
|
|
748
|
+
static void do_basic_init() {
|
749
|
+
gpr_mu_init(&global_connection_polling_mu);
|
750
|
+
gpr_cv_init(&global_connection_polling_cv);
|
751
|
+
}
|
752
|
+
|
740
753
|
/* Temporary fix for
|
741
754
|
* https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899.
|
742
755
|
* Transports in idle channels can get destroyed. Normally c-core re-connects,
|
@@ -748,23 +761,36 @@ static void* set_abort_channel_polling_without_gil(void* arg) {
|
|
748
761
|
* TODO(apolcyn) remove this when core handles new RPCs on dead connections.
|
749
762
|
*/
|
750
763
|
void grpc_rb_channel_polling_thread_start() {
|
751
|
-
|
752
|
-
|
753
|
-
GPR_ASSERT(!
|
754
|
-
GPR_ASSERT(
|
755
|
-
GPR_ASSERT(channel_polling_cq == NULL);
|
756
|
-
|
757
|
-
gpr_mu_init(&global_connection_polling_mu);
|
758
|
-
gpr_cv_init(&global_connection_polling_cv);
|
764
|
+
gpr_once_init(&g_once_init, do_basic_init);
|
765
|
+
GPR_ASSERT(!RTEST(g_channel_polling_thread));
|
766
|
+
GPR_ASSERT(!g_abort_channel_polling);
|
767
|
+
GPR_ASSERT(g_channel_polling_cq == NULL);
|
759
768
|
|
760
|
-
|
761
|
-
|
769
|
+
g_channel_polling_cq = grpc_completion_queue_create_for_next(NULL);
|
770
|
+
g_channel_polling_thread = rb_thread_create(run_poll_channels_loop, NULL);
|
762
771
|
|
763
|
-
if (!RTEST(
|
764
|
-
gpr_log(
|
772
|
+
if (!RTEST(g_channel_polling_thread)) {
|
773
|
+
gpr_log(GPR_ERROR, "GRPC_RUBY: failed to spawn channel polling thread");
|
765
774
|
rb_thread_call_without_gvl(set_abort_channel_polling_without_gil, NULL,
|
766
775
|
NULL, NULL);
|
776
|
+
return;
|
777
|
+
}
|
778
|
+
}
|
779
|
+
|
780
|
+
void grpc_rb_channel_polling_thread_stop() {
|
781
|
+
if (!RTEST(g_channel_polling_thread)) {
|
782
|
+
gpr_log(GPR_ERROR,
|
783
|
+
"GRPC_RUBY: channel polling thread stop: thread was not started");
|
784
|
+
return;
|
767
785
|
}
|
786
|
+
rb_thread_call_without_gvl(run_poll_channels_loop_unblocking_func, NULL, NULL,
|
787
|
+
NULL);
|
788
|
+
rb_funcall(g_channel_polling_thread, rb_intern("join"), 0);
|
789
|
+
// state associated with the channel polling thread is destroyed, reset so
|
790
|
+
// we can start again later
|
791
|
+
g_channel_polling_thread = Qnil;
|
792
|
+
g_abort_channel_polling = false;
|
793
|
+
g_channel_polling_cq = NULL;
|
768
794
|
}
|
769
795
|
|
770
796
|
static void Init_grpc_propagate_masks() {
|
@@ -800,7 +826,9 @@ static void Init_grpc_connectivity_states() {
|
|
800
826
|
}
|
801
827
|
|
802
828
|
void Init_grpc_channel() {
|
829
|
+
rb_global_variable(&g_channel_polling_thread);
|
803
830
|
grpc_rb_cChannelArgs = rb_define_class("TmpChannelArgs", rb_cObject);
|
831
|
+
rb_undef_alloc_func(grpc_rb_cChannelArgs);
|
804
832
|
grpc_rb_cChannel =
|
805
833
|
rb_define_class_under(grpc_rb_mGrpcCore, "Channel", rb_cObject);
|
806
834
|
|
@@ -825,6 +853,7 @@ void Init_grpc_channel() {
|
|
825
853
|
|
826
854
|
id_channel = rb_intern("__channel");
|
827
855
|
id_target = rb_intern("__target");
|
856
|
+
id_channel_recreation_mu = rb_intern("__channel_recreation_mu");
|
828
857
|
rb_define_const(grpc_rb_cChannel, "SSL_TARGET",
|
829
858
|
ID2SYM(rb_intern(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)));
|
830
859
|
rb_define_const(grpc_rb_cChannel, "ENABLE_CENSUS",
|
@@ -24,6 +24,9 @@
|
|
24
24
|
#include "rb_grpc_imports.generated.h"
|
25
25
|
|
26
26
|
#include <grpc/grpc.h>
|
27
|
+
#include <grpc/support/alloc.h>
|
28
|
+
#include <grpc/support/log.h>
|
29
|
+
#include <grpc/support/string_util.h>
|
27
30
|
|
28
31
|
static rb_data_type_t grpc_rb_channel_args_data_type = {
|
29
32
|
"grpc_channel_args",
|
@@ -73,13 +76,14 @@ static int grpc_rb_channel_create_in_process_add_args_hash_cb(VALUE key,
|
|
73
76
|
case T_SYMBOL:
|
74
77
|
args->args[args->num_args - 1].type = GRPC_ARG_STRING;
|
75
78
|
args->args[args->num_args - 1].value.string =
|
76
|
-
(
|
79
|
+
gpr_strdup(rb_id2name(SYM2ID(val)));
|
77
80
|
--args->num_args;
|
78
81
|
return ST_CONTINUE;
|
79
82
|
|
80
83
|
case T_STRING:
|
81
84
|
args->args[args->num_args - 1].type = GRPC_ARG_STRING;
|
82
|
-
args->args[args->num_args - 1].value.string =
|
85
|
+
args->args[args->num_args - 1].value.string =
|
86
|
+
gpr_strdup(StringValueCStr(val));
|
83
87
|
--args->num_args;
|
84
88
|
return ST_CONTINUE;
|
85
89
|
|
@@ -111,6 +115,7 @@ typedef struct channel_convert_params {
|
|
111
115
|
static VALUE grpc_rb_hash_convert_to_channel_args0(VALUE as_value) {
|
112
116
|
ID id_size = rb_intern("size");
|
113
117
|
VALUE grpc_rb_cChannelArgs = rb_define_class("TmpChannelArgs", rb_cObject);
|
118
|
+
rb_undef_alloc_func(grpc_rb_cChannelArgs);
|
114
119
|
channel_convert_params* params = (channel_convert_params*)as_value;
|
115
120
|
size_t num_args = 0;
|
116
121
|
|
@@ -153,3 +158,15 @@ void grpc_rb_hash_convert_to_channel_args(VALUE src_hash,
|
|
153
158
|
rb_jump_tag(status);
|
154
159
|
}
|
155
160
|
}
|
161
|
+
|
162
|
+
void grpc_rb_channel_args_destroy(grpc_channel_args* args) {
|
163
|
+
GPR_ASSERT(args != NULL);
|
164
|
+
if (args->args == NULL) return;
|
165
|
+
for (int i = 0; i < args->num_args; i++) {
|
166
|
+
if (args->args[i].type == GRPC_ARG_STRING) {
|
167
|
+
// we own string pointers, which were created with gpr_strdup
|
168
|
+
gpr_free(args->args[i].value.string);
|
169
|
+
}
|
170
|
+
}
|
171
|
+
xfree(args->args);
|
172
|
+
}
|
@@ -35,4 +35,8 @@
|
|
35
35
|
void grpc_rb_hash_convert_to_channel_args(VALUE src_hash,
|
36
36
|
grpc_channel_args* dst);
|
37
37
|
|
38
|
+
/* Destroys inner fields of args (does not deallocate the args pointer itself)
|
39
|
+
*/
|
40
|
+
void grpc_rb_channel_args_destroy(grpc_channel_args* args);
|
41
|
+
|
38
42
|
#endif /* GRPC_RB_CHANNEL_ARGS_H_ */
|
@@ -63,7 +63,6 @@ static void grpc_rb_channel_credentials_free_internal(void* p) {
|
|
63
63
|
/* Destroys the credentials instances. */
|
64
64
|
static void grpc_rb_channel_credentials_free(void* p) {
|
65
65
|
grpc_rb_channel_credentials_free_internal(p);
|
66
|
-
grpc_ruby_shutdown();
|
67
66
|
}
|
68
67
|
|
69
68
|
/* Protects the mark object from GC */
|
@@ -29,7 +29,7 @@
|
|
29
29
|
#include <grpc/compression.h>
|
30
30
|
#include <grpc/grpc.h>
|
31
31
|
#include <grpc/impl/codegen/compression_types.h>
|
32
|
-
#include <grpc/impl/
|
32
|
+
#include <grpc/impl/grpc_types.h>
|
33
33
|
#include <grpc/support/alloc.h>
|
34
34
|
#include <grpc/support/log.h>
|
35
35
|
#include <grpc/support/string_util.h>
|
@@ -70,7 +70,6 @@ static void grpc_rb_compression_options_free_internal(void* p) {
|
|
70
70
|
* wrapped grpc compression options. */
|
71
71
|
static void grpc_rb_compression_options_free(void* p) {
|
72
72
|
grpc_rb_compression_options_free_internal(p);
|
73
|
-
grpc_ruby_shutdown();
|
74
73
|
}
|
75
74
|
|
76
75
|
/* Ruby recognized data type for the CompressionOptions class. */
|
@@ -51,6 +51,8 @@ typedef struct grpc_rb_event_queue {
|
|
51
51
|
} grpc_rb_event_queue;
|
52
52
|
|
53
53
|
static grpc_rb_event_queue event_queue;
|
54
|
+
static VALUE g_event_thread = Qnil;
|
55
|
+
static bool g_one_time_init_done = false;
|
54
56
|
|
55
57
|
void grpc_rb_event_queue_enqueue(void (*callback)(void*), void* argument) {
|
56
58
|
grpc_rb_event* event = gpr_malloc(sizeof(grpc_rb_event));
|
@@ -117,7 +119,6 @@ static void grpc_rb_event_unblocking_func(void* arg) {
|
|
117
119
|
static VALUE grpc_rb_event_thread(VALUE arg) {
|
118
120
|
grpc_rb_event* event;
|
119
121
|
(void)arg;
|
120
|
-
grpc_ruby_init();
|
121
122
|
while (true) {
|
122
123
|
event = (grpc_rb_event*)rb_thread_call_without_gvl(
|
123
124
|
grpc_rb_wait_for_event_no_gil, NULL, grpc_rb_event_unblocking_func,
|
@@ -131,15 +132,30 @@ static VALUE grpc_rb_event_thread(VALUE arg) {
|
|
131
132
|
}
|
132
133
|
}
|
133
134
|
grpc_rb_event_queue_destroy();
|
134
|
-
grpc_ruby_shutdown();
|
135
135
|
return Qnil;
|
136
136
|
}
|
137
137
|
|
138
138
|
void grpc_rb_event_queue_thread_start() {
|
139
|
-
|
139
|
+
if (!g_one_time_init_done) {
|
140
|
+
g_one_time_init_done = true;
|
141
|
+
gpr_mu_init(&event_queue.mu);
|
142
|
+
gpr_cv_init(&event_queue.cv);
|
143
|
+
rb_global_variable(&g_event_thread);
|
144
|
+
event_queue.head = event_queue.tail = NULL;
|
145
|
+
}
|
140
146
|
event_queue.abort = false;
|
141
|
-
|
142
|
-
|
147
|
+
GPR_ASSERT(!RTEST(g_event_thread));
|
148
|
+
g_event_thread = rb_thread_create(grpc_rb_event_thread, NULL);
|
149
|
+
}
|
143
150
|
|
144
|
-
|
151
|
+
void grpc_rb_event_queue_thread_stop() {
|
152
|
+
GPR_ASSERT(g_one_time_init_done);
|
153
|
+
if (!RTEST(g_event_thread)) {
|
154
|
+
gpr_log(GPR_ERROR,
|
155
|
+
"GRPC_RUBY: call credentials thread stop: thread not running");
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
rb_thread_call_without_gvl(grpc_rb_event_unblocking_func, NULL, NULL, NULL);
|
159
|
+
rb_funcall(g_event_thread, rb_intern("join"), 0);
|
160
|
+
g_event_thread = Qnil;
|
145
161
|
}
|