grpc 1.56.2-x86_64-linux → 1.57.0-x86_64-linux
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/src/ruby/bin/math_pb.rb +24 -18
- data/src/ruby/ext/grpc/extconf.rb +19 -18
- data/src/ruby/ext/grpc/rb_call.c +62 -39
- data/src/ruby/ext/grpc/rb_call_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_channel.c +109 -84
- data/src/ruby/ext/grpc/rb_channel.h +1 -0
- data/src/ruby/ext/grpc/rb_channel_args.c +16 -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 +0 -1
- 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 +192 -30
- data/src/ruby/ext/grpc/rb_grpc.h +8 -2
- data/src/ruby/ext/grpc/rb_server.c +62 -45
- 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.6/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/2.7/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/3.0/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/3.1/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/3.2/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/generic/bidi_call.rb +2 -0
- data/src/ruby/lib/grpc/version.rb +1 -1
- 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 +25 -111
- data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +25 -2
- metadata +3 -3
@@ -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,24 +218,15 @@ 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,
|
@@ -244,7 +235,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
|
|
244
235
|
}
|
245
236
|
grpc_channel_credentials* insecure_creds =
|
246
237
|
grpc_insecure_credentials_create();
|
247
|
-
ch = grpc_channel_create(target_chars, insecure_creds, &args);
|
238
|
+
ch = grpc_channel_create(target_chars, insecure_creds, &wrapper->args);
|
248
239
|
grpc_channel_credentials_release(insecure_creds);
|
249
240
|
} else {
|
250
241
|
wrapper->credentials = credentials;
|
@@ -257,7 +248,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
|
|
257
248
|
"bad creds, want ChannelCredentials or XdsChannelCredentials");
|
258
249
|
return Qnil;
|
259
250
|
}
|
260
|
-
ch = grpc_channel_create(target_chars, creds, &args);
|
251
|
+
ch = grpc_channel_create(target_chars, creds, &wrapper->args);
|
261
252
|
}
|
262
253
|
|
263
254
|
GPR_ASSERT(ch);
|
@@ -266,16 +257,13 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
|
|
266
257
|
rb_thread_call_without_gvl(
|
267
258
|
channel_init_try_register_connection_polling_without_gil, &stack, NULL,
|
268
259
|
NULL);
|
269
|
-
|
270
|
-
if (args.args != NULL) {
|
271
|
-
xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */
|
272
|
-
}
|
273
260
|
if (ch == NULL) {
|
274
261
|
rb_raise(rb_eRuntimeError, "could not create an rpc channel to target:%s",
|
275
262
|
target_chars);
|
276
263
|
return Qnil;
|
277
264
|
}
|
278
265
|
rb_ivar_set(self, id_target, target);
|
266
|
+
rb_ivar_set(self, id_channel_recreation_mu, rb_mutex_new());
|
279
267
|
return self;
|
280
268
|
}
|
281
269
|
|
@@ -289,7 +277,6 @@ static void* get_state_without_gil(void* arg) {
|
|
289
277
|
get_state_stack* stack = (get_state_stack*)arg;
|
290
278
|
|
291
279
|
gpr_mu_lock(&global_connection_polling_mu);
|
292
|
-
GPR_ASSERT(abort_channel_polling || channel_polling_thread_started);
|
293
280
|
if (stack->bg->channel_destroyed) {
|
294
281
|
stack->out = GRPC_CHANNEL_SHUTDOWN;
|
295
282
|
} else {
|
@@ -346,7 +333,7 @@ static void* wait_for_watch_state_op_complete_without_gvl(void* arg) {
|
|
346
333
|
gpr_mu_lock(&global_connection_polling_mu);
|
347
334
|
// it's unsafe to do a "watch" after "channel polling abort" because the cq
|
348
335
|
// has been shut down.
|
349
|
-
if (
|
336
|
+
if (g_abort_channel_polling || stack->bg_wrapped->channel_destroyed) {
|
350
337
|
gpr_mu_unlock(&global_connection_polling_mu);
|
351
338
|
return (void*)0;
|
352
339
|
}
|
@@ -354,7 +341,7 @@ static void* wait_for_watch_state_op_complete_without_gvl(void* arg) {
|
|
354
341
|
op->op_type = WATCH_STATE_API;
|
355
342
|
grpc_channel_watch_connectivity_state(stack->bg_wrapped->channel,
|
356
343
|
stack->last_state, stack->deadline,
|
357
|
-
|
344
|
+
g_channel_polling_cq, op);
|
358
345
|
|
359
346
|
while (!op->op.api_callback_args.called_back) {
|
360
347
|
gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu,
|
@@ -418,6 +405,51 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
|
|
418
405
|
return op_success ? Qtrue : Qfalse;
|
419
406
|
}
|
420
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
|
+
|
421
453
|
/* Create a call given a grpc_channel, in order to call method. The request
|
422
454
|
is not sent until grpc_call_invoke is called. */
|
423
455
|
static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask,
|
@@ -452,6 +484,11 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask,
|
|
452
484
|
rb_raise(rb_eRuntimeError, "closed!");
|
453
485
|
return Qnil;
|
454
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));
|
455
492
|
|
456
493
|
cq = grpc_completion_queue_create_for_pluck(NULL);
|
457
494
|
method_slice =
|
@@ -581,19 +618,15 @@ static void grpc_rb_channel_try_register_connection_polling(
|
|
581
618
|
bg_watched_channel* bg) {
|
582
619
|
grpc_connectivity_state conn_state;
|
583
620
|
watch_state_op* op = NULL;
|
584
|
-
|
585
|
-
GPR_ASSERT(channel_polling_thread_started || abort_channel_polling);
|
586
|
-
|
587
621
|
if (bg->refcount == 0) {
|
588
622
|
GPR_ASSERT(bg->channel_destroyed);
|
589
623
|
bg_watched_channel_list_free_and_remove(bg);
|
590
624
|
return;
|
591
625
|
}
|
592
626
|
GPR_ASSERT(bg->refcount == 1);
|
593
|
-
if (bg->channel_destroyed ||
|
627
|
+
if (bg->channel_destroyed || g_abort_channel_polling) {
|
594
628
|
return;
|
595
629
|
}
|
596
|
-
|
597
630
|
conn_state = grpc_channel_check_connectivity_state(bg->channel, 0);
|
598
631
|
if (conn_state == GRPC_CHANNEL_SHUTDOWN) {
|
599
632
|
return;
|
@@ -601,13 +634,12 @@ static void grpc_rb_channel_try_register_connection_polling(
|
|
601
634
|
GPR_ASSERT(bg_watched_channel_list_lookup(bg));
|
602
635
|
// prevent bg from being free'd by GC while background thread is watching it
|
603
636
|
bg->refcount++;
|
604
|
-
|
605
637
|
op = gpr_zalloc(sizeof(watch_state_op));
|
606
638
|
op->op_type = CONTINUOUS_WATCH;
|
607
639
|
op->op.continuous_watch_callback_args.bg = bg;
|
608
640
|
grpc_channel_watch_connectivity_state(bg->channel, conn_state,
|
609
641
|
gpr_inf_future(GPR_CLOCK_REALTIME),
|
610
|
-
|
642
|
+
g_channel_polling_cq, op);
|
611
643
|
}
|
612
644
|
|
613
645
|
// Note this loop breaks out with a single call of
|
@@ -624,14 +656,12 @@ static void* run_poll_channels_loop_no_gil(void* arg) {
|
|
624
656
|
gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - begin");
|
625
657
|
|
626
658
|
gpr_mu_lock(&global_connection_polling_mu);
|
627
|
-
GPR_ASSERT(!channel_polling_thread_started);
|
628
|
-
channel_polling_thread_started = 1;
|
629
659
|
gpr_cv_broadcast(&global_connection_polling_cv);
|
630
660
|
gpr_mu_unlock(&global_connection_polling_mu);
|
631
661
|
|
632
662
|
for (;;) {
|
633
663
|
event = grpc_completion_queue_next(
|
634
|
-
|
664
|
+
g_channel_polling_cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
635
665
|
if (event.type == GRPC_QUEUE_SHUTDOWN) {
|
636
666
|
break;
|
637
667
|
}
|
@@ -652,7 +682,7 @@ static void* run_poll_channels_loop_no_gil(void* arg) {
|
|
652
682
|
}
|
653
683
|
gpr_mu_unlock(&global_connection_polling_mu);
|
654
684
|
}
|
655
|
-
grpc_completion_queue_destroy(
|
685
|
+
grpc_completion_queue_destroy(g_channel_polling_cq);
|
656
686
|
gpr_log(GPR_DEBUG,
|
657
687
|
"GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling "
|
658
688
|
"loop");
|
@@ -669,11 +699,11 @@ static void run_poll_channels_loop_unblocking_func(void* arg) {
|
|
669
699
|
"GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting "
|
670
700
|
"connection polling");
|
671
701
|
// early out after first time through
|
672
|
-
if (
|
702
|
+
if (g_abort_channel_polling) {
|
673
703
|
gpr_mu_unlock(&global_connection_polling_mu);
|
674
704
|
return;
|
675
705
|
}
|
676
|
-
|
706
|
+
g_abort_channel_polling = 1;
|
677
707
|
|
678
708
|
// force pending watches to end by switching to shutdown state
|
679
709
|
bg = bg_watched_channel_list_head;
|
@@ -685,7 +715,9 @@ static void run_poll_channels_loop_unblocking_func(void* arg) {
|
|
685
715
|
bg = bg->next;
|
686
716
|
}
|
687
717
|
|
688
|
-
|
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);
|
689
721
|
gpr_cv_broadcast(&global_connection_polling_cv);
|
690
722
|
gpr_mu_unlock(&global_connection_polling_mu);
|
691
723
|
gpr_log(GPR_DEBUG,
|
@@ -699,47 +731,25 @@ static VALUE run_poll_channels_loop(VALUE arg) {
|
|
699
731
|
gpr_log(
|
700
732
|
GPR_DEBUG,
|
701
733
|
"GRPC_RUBY: run_poll_channels_loop - create connection polling thread");
|
702
|
-
grpc_ruby_init();
|
703
734
|
rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL,
|
704
735
|
run_poll_channels_loop_unblocking_func, NULL);
|
705
|
-
grpc_ruby_shutdown();
|
706
736
|
return Qnil;
|
707
737
|
}
|
708
738
|
|
709
|
-
static void* wait_until_channel_polling_thread_started_no_gil(void* arg) {
|
710
|
-
int* stop_waiting = (int*)arg;
|
711
|
-
gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start");
|
712
|
-
gpr_mu_lock(&global_connection_polling_mu);
|
713
|
-
while (!channel_polling_thread_started && !abort_channel_polling &&
|
714
|
-
!*stop_waiting) {
|
715
|
-
gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu,
|
716
|
-
gpr_inf_future(GPR_CLOCK_REALTIME));
|
717
|
-
}
|
718
|
-
gpr_mu_unlock(&global_connection_polling_mu);
|
719
|
-
|
720
|
-
return NULL;
|
721
|
-
}
|
722
|
-
|
723
|
-
static void wait_until_channel_polling_thread_started_unblocking_func(
|
724
|
-
void* arg) {
|
725
|
-
int* stop_waiting = (int*)arg;
|
726
|
-
gpr_mu_lock(&global_connection_polling_mu);
|
727
|
-
gpr_log(GPR_DEBUG,
|
728
|
-
"GRPC_RUBY: interrupt wait for channel polling thread to start");
|
729
|
-
*stop_waiting = 1;
|
730
|
-
gpr_cv_broadcast(&global_connection_polling_cv);
|
731
|
-
gpr_mu_unlock(&global_connection_polling_mu);
|
732
|
-
}
|
733
|
-
|
734
739
|
static void* set_abort_channel_polling_without_gil(void* arg) {
|
735
740
|
(void)arg;
|
736
741
|
gpr_mu_lock(&global_connection_polling_mu);
|
737
|
-
|
742
|
+
g_abort_channel_polling = 1;
|
738
743
|
gpr_cv_broadcast(&global_connection_polling_cv);
|
739
744
|
gpr_mu_unlock(&global_connection_polling_mu);
|
740
745
|
return NULL;
|
741
746
|
}
|
742
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
|
+
|
743
753
|
/* Temporary fix for
|
744
754
|
* https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899.
|
745
755
|
* Transports in idle channels can get destroyed. Normally c-core re-connects,
|
@@ -751,23 +761,36 @@ static void* set_abort_channel_polling_without_gil(void* arg) {
|
|
751
761
|
* TODO(apolcyn) remove this when core handles new RPCs on dead connections.
|
752
762
|
*/
|
753
763
|
void grpc_rb_channel_polling_thread_start() {
|
754
|
-
|
755
|
-
|
756
|
-
GPR_ASSERT(!
|
757
|
-
GPR_ASSERT(
|
758
|
-
GPR_ASSERT(channel_polling_cq == NULL);
|
759
|
-
|
760
|
-
gpr_mu_init(&global_connection_polling_mu);
|
761
|
-
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);
|
762
768
|
|
763
|
-
|
764
|
-
|
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);
|
765
771
|
|
766
|
-
if (!RTEST(
|
767
|
-
gpr_log(
|
772
|
+
if (!RTEST(g_channel_polling_thread)) {
|
773
|
+
gpr_log(GPR_ERROR, "GRPC_RUBY: failed to spawn channel polling thread");
|
768
774
|
rb_thread_call_without_gvl(set_abort_channel_polling_without_gil, NULL,
|
769
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;
|
770
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;
|
771
794
|
}
|
772
795
|
|
773
796
|
static void Init_grpc_propagate_masks() {
|
@@ -803,6 +826,7 @@ static void Init_grpc_connectivity_states() {
|
|
803
826
|
}
|
804
827
|
|
805
828
|
void Init_grpc_channel() {
|
829
|
+
rb_global_variable(&g_channel_polling_thread);
|
806
830
|
grpc_rb_cChannelArgs = rb_define_class("TmpChannelArgs", rb_cObject);
|
807
831
|
rb_undef_alloc_func(grpc_rb_cChannelArgs);
|
808
832
|
grpc_rb_cChannel =
|
@@ -829,6 +853,7 @@ void Init_grpc_channel() {
|
|
829
853
|
|
830
854
|
id_channel = rb_intern("__channel");
|
831
855
|
id_target = rb_intern("__target");
|
856
|
+
id_channel_recreation_mu = rb_intern("__channel_recreation_mu");
|
832
857
|
rb_define_const(grpc_rb_cChannel, "SSL_TARGET",
|
833
858
|
ID2SYM(rb_intern(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)));
|
834
859
|
rb_define_const(grpc_rb_cChannel, "ENABLE_CENSUS",
|
@@ -24,6 +24,7 @@
|
|
24
24
|
#include "rb_grpc_imports.generated.h"
|
25
25
|
|
26
26
|
#include <grpc/grpc.h>
|
27
|
+
#include <grpc/support/log.h>
|
27
28
|
|
28
29
|
static rb_data_type_t grpc_rb_channel_args_data_type = {
|
29
30
|
"grpc_channel_args",
|
@@ -73,13 +74,14 @@ static int grpc_rb_channel_create_in_process_add_args_hash_cb(VALUE key,
|
|
73
74
|
case T_SYMBOL:
|
74
75
|
args->args[args->num_args - 1].type = GRPC_ARG_STRING;
|
75
76
|
args->args[args->num_args - 1].value.string =
|
76
|
-
(
|
77
|
+
strdup(rb_id2name(SYM2ID(val)));
|
77
78
|
--args->num_args;
|
78
79
|
return ST_CONTINUE;
|
79
80
|
|
80
81
|
case T_STRING:
|
81
82
|
args->args[args->num_args - 1].type = GRPC_ARG_STRING;
|
82
|
-
args->args[args->num_args - 1].value.string =
|
83
|
+
args->args[args->num_args - 1].value.string =
|
84
|
+
strdup(StringValueCStr(val));
|
83
85
|
--args->num_args;
|
84
86
|
return ST_CONTINUE;
|
85
87
|
|
@@ -154,3 +156,15 @@ void grpc_rb_hash_convert_to_channel_args(VALUE src_hash,
|
|
154
156
|
rb_jump_tag(status);
|
155
157
|
}
|
156
158
|
}
|
159
|
+
|
160
|
+
void grpc_rb_channel_args_destroy(grpc_channel_args* args) {
|
161
|
+
GPR_ASSERT(args != NULL);
|
162
|
+
if (args->args == NULL) return;
|
163
|
+
for (int i = 0; i < args->num_args; i++) {
|
164
|
+
if (args->args[i].type == GRPC_ARG_STRING) {
|
165
|
+
// we own string pointers, which were created with strdup
|
166
|
+
free(args->args[i].value.string);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
xfree(args->args);
|
170
|
+
}
|
@@ -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 */
|
@@ -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
|
}
|