grpc 1.42.0.pre1-arm64-darwin → 1.58.3-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/grpc_c.64-ucrt.ruby +0 -0
  3. data/src/ruby/bin/math_pb.rb +24 -18
  4. data/src/ruby/ext/grpc/ext-export-truffleruby-with-ruby-abi-version.clang +2 -0
  5. data/src/ruby/ext/grpc/ext-export-truffleruby-with-ruby-abi-version.gcc +7 -0
  6. data/src/ruby/ext/grpc/ext-export-with-ruby-abi-version.clang +2 -0
  7. data/src/ruby/ext/grpc/ext-export-with-ruby-abi-version.gcc +7 -0
  8. data/src/ruby/ext/grpc/ext-export.gcc +1 -1
  9. data/src/ruby/ext/grpc/extconf.rb +117 -32
  10. data/src/ruby/ext/grpc/rb_call.c +63 -39
  11. data/src/ruby/ext/grpc/rb_call_credentials.c +0 -1
  12. data/src/ruby/ext/grpc/rb_channel.c +113 -84
  13. data/src/ruby/ext/grpc/rb_channel.h +1 -0
  14. data/src/ruby/ext/grpc/rb_channel_args.c +17 -2
  15. data/src/ruby/ext/grpc/rb_channel_args.h +4 -0
  16. data/src/ruby/ext/grpc/rb_channel_credentials.c +0 -1
  17. data/src/ruby/ext/grpc/rb_compression_options.c +1 -2
  18. data/src/ruby/ext/grpc/rb_event_thread.c +22 -6
  19. data/src/ruby/ext/grpc/rb_event_thread.h +1 -0
  20. data/src/ruby/ext/grpc/rb_grpc.c +193 -30
  21. data/src/ruby/ext/grpc/rb_grpc.h +8 -2
  22. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +66 -72
  23. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +102 -111
  24. data/src/ruby/ext/grpc/rb_loader.c +6 -2
  25. data/src/ruby/ext/grpc/rb_server.c +69 -49
  26. data/src/ruby/ext/grpc/rb_server_credentials.c +0 -1
  27. data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +0 -1
  28. data/src/ruby/ext/grpc/rb_xds_server_credentials.c +0 -1
  29. data/src/ruby/lib/grpc/2.6/grpc_c.bundle +0 -0
  30. data/src/ruby/lib/grpc/2.7/grpc_c.bundle +0 -0
  31. data/src/ruby/lib/grpc/3.0/grpc_c.bundle +0 -0
  32. data/src/ruby/lib/grpc/3.1/grpc_c.bundle +0 -0
  33. data/src/ruby/lib/grpc/3.2/grpc_c.bundle +0 -0
  34. data/src/ruby/lib/grpc/errors.rb +1 -1
  35. data/src/ruby/lib/grpc/generic/active_call.rb +16 -15
  36. data/src/ruby/lib/grpc/generic/bidi_call.rb +4 -0
  37. data/src/ruby/lib/grpc/grpc.rb +1 -1
  38. data/src/ruby/lib/grpc/version.rb +1 -1
  39. data/src/ruby/pb/generate_proto_ruby.sh +1 -6
  40. data/src/ruby/pb/grpc/health/v1/health_pb.rb +24 -13
  41. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +24 -3
  42. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +26 -108
  43. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +27 -3
  44. data/src/ruby/pb/test/client.rb +16 -0
  45. data/src/ruby/spec/channel_spec.rb +5 -43
  46. data/src/ruby/spec/client_server_spec.rb +20 -8
  47. data/src/ruby/spec/generic/active_call_spec.rb +12 -3
  48. data/src/ruby/spec/generic/client_stub_spec.rb +23 -23
  49. data/src/ruby/spec/generic/rpc_server_spec.rb +3 -3
  50. data/src/ruby/spec/generic/server_interceptors_spec.rb +1 -1
  51. data/src/ruby/spec/user_agent_spec.rb +1 -1
  52. metadata +61 -59
  53. data/src/ruby/lib/grpc/2.4/grpc_c.bundle +0 -0
  54. data/src/ruby/lib/grpc/2.5/grpc_c.bundle +0 -0
  55. /data/{grpc_c.32.ruby → grpc_c.32-msvcrt.ruby} +0 -0
  56. /data/{grpc_c.64.ruby → grpc_c.64-msvcrt.ruby} +0 -0
@@ -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 grpc_ruby_set_init_pid(void) {}
228
- static bool grpc_ruby_forked_after_init(void) { return false; }
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 grpc_init_pid;
248
+ static pid_t g_init_pid;
249
+ static long g_init_tid;
231
250
 
232
- static void grpc_ruby_set_init_pid(void) {
233
- GPR_ASSERT(grpc_init_pid == 0);
234
- grpc_init_pid = getpid();
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 grpc_ruby_forked_after_init(void) {
238
- GPR_ASSERT(grpc_init_pid != 0);
239
- return grpc_init_pid != getpid();
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 (grpc_ruby_forked_after_init()) {
263
- rb_raise(rb_eRuntimeError, "grpc cannot be used before and after forking");
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 bg_thread_init_rb_mu = Qundef;
268
- static int bg_thread_init_done = 0;
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
- rb_mutex_lock(bg_thread_init_rb_mu);
276
- if (!bg_thread_init_done) {
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
- bg_thread_init_done = 1;
339
+ g_bg_thread_init_done = true;
280
340
  }
281
- rb_mutex_unlock(bg_thread_init_rb_mu);
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, grpc_ruby_set_init_pid);
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 g_grpc_ruby_init_count:%" PRId64,
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
- void grpc_ruby_shutdown() {
297
- GPR_ASSERT(g_grpc_ruby_init_count > 0);
298
- if (!grpc_ruby_forked_after_init()) grpc_shutdown();
299
- gpr_log(
300
- GPR_DEBUG,
301
- "GRPC_RUBY: grpc_ruby_shutdown - prev g_grpc_ruby_init_count:%" PRId64,
302
- g_grpc_ruby_init_count--);
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(&bg_thread_init_rb_mu);
312
- bg_thread_init_rb_mu = rb_mutex_new();
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
  }
@@ -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
- void grpc_ruby_init();
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 grpc_ruby_shutdown();
81
+ void grpc_ruby_init();
76
82
 
77
83
  #endif /* GRPC_RB_H_ */