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
data/src/ruby/ext/grpc/rb_grpc.c
CHANGED
@@ -44,6 +44,11 @@
|
|
44
44
|
#include <grpc/support/log.h>
|
45
45
|
#include <grpc/support/time.h>
|
46
46
|
|
47
|
+
#ifdef GPR_LINUX
|
48
|
+
#include <sys/syscall.h>
|
49
|
+
#include <unistd.h>
|
50
|
+
#endif
|
51
|
+
|
47
52
|
static VALUE grpc_rb_cTimeVal = Qnil;
|
48
53
|
|
49
54
|
static rb_data_type_t grpc_rb_timespec_data_type = {
|
@@ -198,6 +203,7 @@ static void Init_grpc_time_consts() {
|
|
198
203
|
rb_define_module_under(grpc_rb_mGrpcCore, "TimeConsts");
|
199
204
|
grpc_rb_cTimeVal =
|
200
205
|
rb_define_class_under(grpc_rb_mGrpcCore, "TimeSpec", rb_cObject);
|
206
|
+
rb_undef_alloc_func(grpc_rb_cTimeVal);
|
201
207
|
zero_realtime = gpr_time_0(GPR_CLOCK_REALTIME);
|
202
208
|
inf_future_realtime = gpr_inf_future(GPR_CLOCK_REALTIME);
|
203
209
|
inf_past_realtime = gpr_inf_past(GPR_CLOCK_REALTIME);
|
@@ -223,20 +229,51 @@ static void Init_grpc_time_consts() {
|
|
223
229
|
id_tv_nsec = rb_intern("tv_nsec");
|
224
230
|
}
|
225
231
|
|
232
|
+
static bool g_enable_fork_support;
|
233
|
+
|
234
|
+
#ifdef GPR_LINUX
|
235
|
+
static long sys_gettid() { return syscall(__NR_gettid); }
|
236
|
+
static bool can_enable_fork_support() { return true; }
|
237
|
+
#else
|
238
|
+
static long sys_gettid() { return 0; }
|
239
|
+
static bool can_enable_fork_support() { return false; }
|
240
|
+
#endif
|
241
|
+
|
226
242
|
#if GPR_WINDOWS
|
227
|
-
static void
|
228
|
-
static bool
|
243
|
+
static void grpc_ruby_basic_init(void) {}
|
244
|
+
static bool grpc_ruby_initial_pid(void) { return true; }
|
245
|
+
static bool grpc_ruby_initial_thread(void) { return true; }
|
246
|
+
static void grpc_ruby_reset_init_state(void) {}
|
229
247
|
#else
|
230
|
-
static pid_t
|
248
|
+
static pid_t g_init_pid;
|
249
|
+
static long g_init_tid;
|
231
250
|
|
232
|
-
static
|
233
|
-
GPR_ASSERT(
|
234
|
-
|
251
|
+
static bool grpc_ruby_initial_pid(void) {
|
252
|
+
GPR_ASSERT(g_init_pid != 0);
|
253
|
+
return g_init_pid == getpid();
|
235
254
|
}
|
236
255
|
|
237
|
-
static bool
|
238
|
-
GPR_ASSERT(
|
239
|
-
return
|
256
|
+
static bool grpc_ruby_initial_thread(void) {
|
257
|
+
GPR_ASSERT(g_init_tid != 0);
|
258
|
+
return sys_gettid() == g_init_tid;
|
259
|
+
}
|
260
|
+
|
261
|
+
static void grpc_ruby_reset_init_state(void) {
|
262
|
+
g_init_pid = getpid();
|
263
|
+
g_init_tid = sys_gettid();
|
264
|
+
}
|
265
|
+
|
266
|
+
static void grpc_ruby_basic_init(void) {
|
267
|
+
GPR_ASSERT(g_init_pid == 0);
|
268
|
+
GPR_ASSERT(g_init_tid == 0);
|
269
|
+
grpc_ruby_reset_init_state();
|
270
|
+
// TODO(apolcyn): ideally, we should share logic with C-core
|
271
|
+
// for determining whether or not fork support is enabled, rather
|
272
|
+
// than parsing the environment variable ourselves.
|
273
|
+
const char* res = getenv("GRPC_ENABLE_FORK_SUPPORT");
|
274
|
+
if (res != NULL && strcmp(res, "1") == 0) {
|
275
|
+
g_enable_fork_support = can_enable_fork_support();
|
276
|
+
}
|
240
277
|
}
|
241
278
|
#endif
|
242
279
|
|
@@ -257,59 +294,175 @@ VALUE sym_details = Qundef;
|
|
257
294
|
VALUE sym_metadata = Qundef;
|
258
295
|
|
259
296
|
static gpr_once g_once_init = GPR_ONCE_INIT;
|
297
|
+
static int64_t g_grpc_rb_prefork_pending; // synchronized by the GIL
|
298
|
+
static int64_t g_grpc_rb_num_fork_unsafe_threads; // synchronized by the GIL
|
260
299
|
|
261
300
|
void grpc_ruby_fork_guard() {
|
262
|
-
if
|
263
|
-
|
301
|
+
// Check if we're using gRPC between prefork and postfork
|
302
|
+
gpr_once_init(&g_once_init, grpc_ruby_basic_init);
|
303
|
+
if (g_grpc_rb_prefork_pending) {
|
304
|
+
rb_raise(rb_eRuntimeError,
|
305
|
+
"grpc cannot be used between calls to GRPC.prefork and "
|
306
|
+
"GRPC.postfork_child or GRPC.postfork_parent");
|
307
|
+
}
|
308
|
+
if (!grpc_ruby_initial_pid()) {
|
309
|
+
if (g_enable_fork_support) {
|
310
|
+
// Only way we can get here is by enabling for support and forking but not
|
311
|
+
// calling prefork
|
312
|
+
rb_raise(rb_eRuntimeError,
|
313
|
+
"grpc is in a broken state: GRPC.prefork must be called before "
|
314
|
+
"calling fork from a process using grpc");
|
315
|
+
} else {
|
316
|
+
rb_raise(rb_eRuntimeError,
|
317
|
+
"grpc cannot be used before and after forking unless the "
|
318
|
+
"GRPC_ENABLE_FORK_SUPPORT env var is set to \"1\" and the "
|
319
|
+
"platform supports it (linux only)");
|
320
|
+
}
|
264
321
|
}
|
265
322
|
}
|
266
323
|
|
267
|
-
static VALUE
|
268
|
-
static
|
324
|
+
static VALUE g_bg_thread_init_rb_mu = Qundef;
|
325
|
+
static bool g_bg_thread_init_done;
|
269
326
|
|
270
327
|
static void grpc_ruby_init_threads() {
|
271
328
|
// Avoid calling into ruby library (when creating threads here)
|
272
329
|
// in gpr_once_init. In general, it appears to be unsafe to call
|
273
330
|
// into the ruby library while holding a non-ruby mutex, because a gil yield
|
274
331
|
// could end up trying to lock onto that same mutex and deadlocking.
|
275
|
-
|
276
|
-
|
332
|
+
gpr_log(GPR_INFO,
|
333
|
+
"GRPC_RUBY: grpc_ruby_init_threads g_bg_thread_init_done=%d",
|
334
|
+
g_bg_thread_init_done);
|
335
|
+
rb_mutex_lock(g_bg_thread_init_rb_mu);
|
336
|
+
if (!g_bg_thread_init_done) {
|
277
337
|
grpc_rb_event_queue_thread_start();
|
278
338
|
grpc_rb_channel_polling_thread_start();
|
279
|
-
|
339
|
+
g_bg_thread_init_done = true;
|
280
340
|
}
|
281
|
-
rb_mutex_unlock(
|
341
|
+
rb_mutex_unlock(g_bg_thread_init_rb_mu);
|
282
342
|
}
|
283
343
|
|
284
344
|
static int64_t g_grpc_ruby_init_count;
|
285
345
|
|
286
346
|
void grpc_ruby_init() {
|
287
|
-
gpr_once_init(&g_once_init,
|
347
|
+
gpr_once_init(&g_once_init, grpc_ruby_basic_init);
|
348
|
+
grpc_ruby_fork_guard();
|
288
349
|
grpc_init();
|
289
350
|
grpc_ruby_init_threads();
|
290
351
|
// (only gpr_log after logging has been initialized)
|
291
352
|
gpr_log(GPR_DEBUG,
|
292
|
-
"GRPC_RUBY: grpc_ruby_init - prev
|
293
|
-
g_grpc_ruby_init_count
|
353
|
+
"GRPC_RUBY: grpc_ruby_init - g_enable_fork_support=%d prev "
|
354
|
+
"g_grpc_ruby_init_count:%" PRId64,
|
355
|
+
g_enable_fork_support, g_grpc_ruby_init_count++);
|
356
|
+
}
|
357
|
+
|
358
|
+
// fork APIs, useable on linux with env var: GRPC_ENABLE_FORK_SUPPORT=1
|
359
|
+
//
|
360
|
+
// Must be called once and only once before forking. Must be called on the
|
361
|
+
// same threads that gRPC was (lazy-)initialized on. One must not call
|
362
|
+
// into the gRPC library during or after prefork has been called, until
|
363
|
+
// the corresponding postfork_{parent,child} APIs have been called.
|
364
|
+
static VALUE grpc_rb_prefork(VALUE self) {
|
365
|
+
// This might be the first time we've called into the grpc library, so make
|
366
|
+
// sure basic one-time initialization is taken care of. Note that if this is
|
367
|
+
// the case, then grpc_init() will start up c-core threads; that's OK since
|
368
|
+
// they will be shut down in C-core's pthread_atfork handler.
|
369
|
+
gpr_once_init(&g_once_init, grpc_ruby_basic_init);
|
370
|
+
grpc_init();
|
371
|
+
if (!g_enable_fork_support) {
|
372
|
+
rb_raise(rb_eRuntimeError,
|
373
|
+
"forking with gRPC/Ruby is only supported on linux with env var: "
|
374
|
+
"GRPC_ENABLE_FORK_SUPPORT=1");
|
375
|
+
}
|
376
|
+
if (g_grpc_rb_prefork_pending) {
|
377
|
+
rb_raise(rb_eRuntimeError,
|
378
|
+
"GRPC.prefork already called without a matching "
|
379
|
+
"GRPC.postfork_{parent,child}");
|
380
|
+
}
|
381
|
+
if (!grpc_ruby_initial_thread()) {
|
382
|
+
rb_raise(rb_eRuntimeError,
|
383
|
+
"GRPC.prefork and fork need to be called from the same thread "
|
384
|
+
"that GRPC was initialized on (GRPC lazy-initializes when when "
|
385
|
+
"the first GRPC object is created");
|
386
|
+
}
|
387
|
+
if (g_grpc_rb_num_fork_unsafe_threads > 0) {
|
388
|
+
rb_raise(
|
389
|
+
rb_eRuntimeError,
|
390
|
+
"Detected at least %ld threads actively using grpc, so it is not safe "
|
391
|
+
"call GRPC.prefork or fork. Note that grpc-ruby servers and "
|
392
|
+
"bidirectional "
|
393
|
+
"streams manage background threads and are not fork safe.",
|
394
|
+
g_grpc_rb_num_fork_unsafe_threads);
|
395
|
+
}
|
396
|
+
g_grpc_rb_prefork_pending = true;
|
397
|
+
rb_mutex_lock(g_bg_thread_init_rb_mu);
|
398
|
+
if (g_bg_thread_init_done) {
|
399
|
+
grpc_rb_channel_polling_thread_stop();
|
400
|
+
grpc_rb_event_queue_thread_stop();
|
401
|
+
// all ruby-level background threads joined at this point
|
402
|
+
g_bg_thread_init_done = false;
|
403
|
+
}
|
404
|
+
rb_mutex_unlock(g_bg_thread_init_rb_mu);
|
405
|
+
return Qnil;
|
294
406
|
}
|
295
407
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
408
|
+
static VALUE grpc_rb_postfork_child(VALUE self) {
|
409
|
+
if (!g_grpc_rb_prefork_pending) {
|
410
|
+
rb_raise(rb_eRuntimeError,
|
411
|
+
"GRPC::postfork_child can only be called once following a "
|
412
|
+
"GRPC::prefork");
|
413
|
+
}
|
414
|
+
if (grpc_ruby_initial_pid()) {
|
415
|
+
rb_raise(rb_eRuntimeError,
|
416
|
+
"GRPC.postfork_child must be called only from the child process "
|
417
|
+
"after a fork");
|
418
|
+
}
|
419
|
+
grpc_ruby_reset_init_state();
|
420
|
+
grpc_ruby_init_threads();
|
421
|
+
g_grpc_rb_prefork_pending = false;
|
422
|
+
return Qnil;
|
303
423
|
}
|
304
424
|
|
425
|
+
static VALUE grpc_rb_postfork_parent(VALUE self) {
|
426
|
+
// TODO(apolcyn): check calling thread vs. thread that gRPC was initialized on
|
427
|
+
if (!g_grpc_rb_prefork_pending) {
|
428
|
+
rb_raise(rb_eRuntimeError,
|
429
|
+
"GRPC::postfork_parent can only be called once following a "
|
430
|
+
"GRPC::prefork");
|
431
|
+
}
|
432
|
+
if (!grpc_ruby_initial_pid()) {
|
433
|
+
rb_raise(rb_eRuntimeError,
|
434
|
+
"GRPC.postfork_parent must be called only from the parent process "
|
435
|
+
"after a fork");
|
436
|
+
}
|
437
|
+
if (!grpc_ruby_initial_thread()) {
|
438
|
+
rb_raise(rb_eRuntimeError,
|
439
|
+
"GRPC.postfork_parent needs to be called from the same thread "
|
440
|
+
"that GRPC.prefork (and fork) was called from");
|
441
|
+
}
|
442
|
+
grpc_ruby_init_threads();
|
443
|
+
g_grpc_rb_prefork_pending = false;
|
444
|
+
return Qnil;
|
445
|
+
}
|
446
|
+
|
447
|
+
// APIs to mark fork-unsafe sections from C-extension code
|
448
|
+
void grpc_rb_fork_unsafe_begin() { g_grpc_rb_num_fork_unsafe_threads++; }
|
449
|
+
|
450
|
+
void grpc_rb_fork_unsafe_end() { g_grpc_rb_num_fork_unsafe_threads--; }
|
451
|
+
|
452
|
+
// APIs to mark fork-unsafe sections from ruby code
|
453
|
+
static VALUE grpc_rb_fork_unsafe_begin_api() { grpc_rb_fork_unsafe_begin(); }
|
454
|
+
|
455
|
+
static VALUE grpc_rb_fork_unsafe_end_api() { grpc_rb_fork_unsafe_end(); }
|
456
|
+
|
457
|
+
// One-time initialization
|
305
458
|
void Init_grpc_c() {
|
306
459
|
if (!grpc_rb_load_core()) {
|
307
460
|
rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
|
308
461
|
return;
|
309
462
|
}
|
310
463
|
|
311
|
-
rb_global_variable(&
|
312
|
-
|
464
|
+
rb_global_variable(&g_bg_thread_init_rb_mu);
|
465
|
+
g_bg_thread_init_rb_mu = rb_mutex_new();
|
313
466
|
|
314
467
|
grpc_rb_mGRPC = rb_define_module("GRPC");
|
315
468
|
grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
|
@@ -319,7 +472,7 @@ void Init_grpc_c() {
|
|
319
472
|
sym_code = ID2SYM(rb_intern("code"));
|
320
473
|
sym_details = ID2SYM(rb_intern("details"));
|
321
474
|
sym_metadata = ID2SYM(rb_intern("metadata"));
|
322
|
-
|
475
|
+
// init C-defined classes
|
323
476
|
Init_grpc_channel();
|
324
477
|
Init_grpc_call();
|
325
478
|
Init_grpc_call_credentials();
|
@@ -330,4 +483,14 @@ void Init_grpc_c() {
|
|
330
483
|
Init_grpc_xds_server_credentials();
|
331
484
|
Init_grpc_time_consts();
|
332
485
|
Init_grpc_compression_options();
|
486
|
+
// define fork APIs
|
487
|
+
rb_define_module_function(grpc_rb_mGRPC, "prefork", grpc_rb_prefork, 0);
|
488
|
+
rb_define_module_function(grpc_rb_mGRPC, "postfork_child",
|
489
|
+
grpc_rb_postfork_child, 0);
|
490
|
+
rb_define_module_function(grpc_rb_mGRPC, "postfork_parent",
|
491
|
+
grpc_rb_postfork_parent, 0);
|
492
|
+
rb_define_module_function(grpc_rb_mGrpcCore, "fork_unsafe_begin",
|
493
|
+
grpc_rb_fork_unsafe_begin_api, 0);
|
494
|
+
rb_define_module_function(grpc_rb_mGrpcCore, "fork_unsafe_end",
|
495
|
+
grpc_rb_fork_unsafe_end_api, 0);
|
333
496
|
}
|
data/src/ruby/ext/grpc/rb_grpc.h
CHANGED
@@ -70,8 +70,14 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval);
|
|
70
70
|
|
71
71
|
void grpc_ruby_fork_guard();
|
72
72
|
|
73
|
-
|
73
|
+
/* To be called once and only once before entering code section that is
|
74
|
+
* definitely not fork-safe. Used in conjunction with GRPC.prefork
|
75
|
+
* to catch for-unsafe processes and raise errors. */
|
76
|
+
void grpc_rb_fork_unsafe_begin();
|
77
|
+
|
78
|
+
/* To be called once and only once after each grpc_rb_fork_unsafe_begin*/
|
79
|
+
void grpc_rb_fork_unsafe_end();
|
74
80
|
|
75
|
-
void
|
81
|
+
void grpc_ruby_init();
|
76
82
|
|
77
83
|
#endif /* GRPC_RB_H_ */
|