grpc 1.56.0-x86_64-linux → 1.57.0.pre1-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +126 -49
- 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_grpc_imports.generated.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
- 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 +5 -5
@@ -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
|
}
|
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 = {
|
@@ -224,20 +229,51 @@ static void Init_grpc_time_consts() {
|
|
224
229
|
id_tv_nsec = rb_intern("tv_nsec");
|
225
230
|
}
|
226
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
|
+
|
227
242
|
#if GPR_WINDOWS
|
228
|
-
static void
|
229
|
-
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) {}
|
230
247
|
#else
|
231
|
-
static pid_t
|
248
|
+
static pid_t g_init_pid;
|
249
|
+
static long g_init_tid;
|
232
250
|
|
233
|
-
static
|
234
|
-
GPR_ASSERT(
|
235
|
-
|
251
|
+
static bool grpc_ruby_initial_pid(void) {
|
252
|
+
GPR_ASSERT(g_init_pid != 0);
|
253
|
+
return g_init_pid == getpid();
|
236
254
|
}
|
237
255
|
|
238
|
-
static bool
|
239
|
-
GPR_ASSERT(
|
240
|
-
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
|
+
}
|
241
277
|
}
|
242
278
|
#endif
|
243
279
|
|
@@ -258,59 +294,175 @@ VALUE sym_details = Qundef;
|
|
258
294
|
VALUE sym_metadata = Qundef;
|
259
295
|
|
260
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
|
261
299
|
|
262
300
|
void grpc_ruby_fork_guard() {
|
263
|
-
if
|
264
|
-
|
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
|
+
}
|
265
321
|
}
|
266
322
|
}
|
267
323
|
|
268
|
-
static VALUE
|
269
|
-
static
|
324
|
+
static VALUE g_bg_thread_init_rb_mu = Qundef;
|
325
|
+
static bool g_bg_thread_init_done;
|
270
326
|
|
271
327
|
static void grpc_ruby_init_threads() {
|
272
328
|
// Avoid calling into ruby library (when creating threads here)
|
273
329
|
// in gpr_once_init. In general, it appears to be unsafe to call
|
274
330
|
// into the ruby library while holding a non-ruby mutex, because a gil yield
|
275
331
|
// could end up trying to lock onto that same mutex and deadlocking.
|
276
|
-
|
277
|
-
|
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) {
|
278
337
|
grpc_rb_event_queue_thread_start();
|
279
338
|
grpc_rb_channel_polling_thread_start();
|
280
|
-
|
339
|
+
g_bg_thread_init_done = true;
|
281
340
|
}
|
282
|
-
rb_mutex_unlock(
|
341
|
+
rb_mutex_unlock(g_bg_thread_init_rb_mu);
|
283
342
|
}
|
284
343
|
|
285
344
|
static int64_t g_grpc_ruby_init_count;
|
286
345
|
|
287
346
|
void grpc_ruby_init() {
|
288
|
-
gpr_once_init(&g_once_init,
|
347
|
+
gpr_once_init(&g_once_init, grpc_ruby_basic_init);
|
348
|
+
grpc_ruby_fork_guard();
|
289
349
|
grpc_init();
|
290
350
|
grpc_ruby_init_threads();
|
291
351
|
// (only gpr_log after logging has been initialized)
|
292
352
|
gpr_log(GPR_DEBUG,
|
293
|
-
"GRPC_RUBY: grpc_ruby_init - prev
|
294
|
-
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;
|
295
406
|
}
|
296
407
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
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;
|
304
423
|
}
|
305
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
|
306
458
|
void Init_grpc_c() {
|
307
459
|
if (!grpc_rb_load_core()) {
|
308
460
|
rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
|
309
461
|
return;
|
310
462
|
}
|
311
463
|
|
312
|
-
rb_global_variable(&
|
313
|
-
|
464
|
+
rb_global_variable(&g_bg_thread_init_rb_mu);
|
465
|
+
g_bg_thread_init_rb_mu = rb_mutex_new();
|
314
466
|
|
315
467
|
grpc_rb_mGRPC = rb_define_module("GRPC");
|
316
468
|
grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
|
@@ -320,7 +472,7 @@ void Init_grpc_c() {
|
|
320
472
|
sym_code = ID2SYM(rb_intern("code"));
|
321
473
|
sym_details = ID2SYM(rb_intern("details"));
|
322
474
|
sym_metadata = ID2SYM(rb_intern("metadata"));
|
323
|
-
|
475
|
+
// init C-defined classes
|
324
476
|
Init_grpc_channel();
|
325
477
|
Init_grpc_call();
|
326
478
|
Init_grpc_call_credentials();
|
@@ -331,4 +483,14 @@ void Init_grpc_c() {
|
|
331
483
|
Init_grpc_xds_server_credentials();
|
332
484
|
Init_grpc_time_consts();
|
333
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);
|
334
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_ */
|
@@ -188,6 +188,7 @@ grpc_tls_credentials_options_set_identity_cert_name_type grpc_tls_credentials_op
|
|
188
188
|
grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import;
|
189
189
|
grpc_tls_credentials_options_set_crl_directory_type grpc_tls_credentials_options_set_crl_directory_import;
|
190
190
|
grpc_tls_credentials_options_set_verify_server_cert_type grpc_tls_credentials_options_set_verify_server_cert_import;
|
191
|
+
grpc_tls_credentials_options_set_send_client_ca_list_type grpc_tls_credentials_options_set_send_client_ca_list_import;
|
191
192
|
grpc_tls_credentials_options_set_check_call_host_type grpc_tls_credentials_options_set_check_call_host_import;
|
192
193
|
grpc_insecure_credentials_create_type grpc_insecure_credentials_create_import;
|
193
194
|
grpc_insecure_server_credentials_create_type grpc_insecure_server_credentials_create_import;
|
@@ -474,6 +475,7 @@ void grpc_rb_load_imports(HMODULE library) {
|
|
474
475
|
grpc_tls_credentials_options_set_cert_request_type_import = (grpc_tls_credentials_options_set_cert_request_type_type) GetProcAddress(library, "grpc_tls_credentials_options_set_cert_request_type");
|
475
476
|
grpc_tls_credentials_options_set_crl_directory_import = (grpc_tls_credentials_options_set_crl_directory_type) GetProcAddress(library, "grpc_tls_credentials_options_set_crl_directory");
|
476
477
|
grpc_tls_credentials_options_set_verify_server_cert_import = (grpc_tls_credentials_options_set_verify_server_cert_type) GetProcAddress(library, "grpc_tls_credentials_options_set_verify_server_cert");
|
478
|
+
grpc_tls_credentials_options_set_send_client_ca_list_import = (grpc_tls_credentials_options_set_send_client_ca_list_type) GetProcAddress(library, "grpc_tls_credentials_options_set_send_client_ca_list");
|
477
479
|
grpc_tls_credentials_options_set_check_call_host_import = (grpc_tls_credentials_options_set_check_call_host_type) GetProcAddress(library, "grpc_tls_credentials_options_set_check_call_host");
|
478
480
|
grpc_insecure_credentials_create_import = (grpc_insecure_credentials_create_type) GetProcAddress(library, "grpc_insecure_credentials_create");
|
479
481
|
grpc_insecure_server_credentials_create_import = (grpc_insecure_server_credentials_create_type) GetProcAddress(library, "grpc_insecure_server_credentials_create");
|
@@ -539,6 +539,9 @@ extern grpc_tls_credentials_options_set_crl_directory_type grpc_tls_credentials_
|
|
539
539
|
typedef void(*grpc_tls_credentials_options_set_verify_server_cert_type)(grpc_tls_credentials_options* options, int verify_server_cert);
|
540
540
|
extern grpc_tls_credentials_options_set_verify_server_cert_type grpc_tls_credentials_options_set_verify_server_cert_import;
|
541
541
|
#define grpc_tls_credentials_options_set_verify_server_cert grpc_tls_credentials_options_set_verify_server_cert_import
|
542
|
+
typedef void(*grpc_tls_credentials_options_set_send_client_ca_list_type)(grpc_tls_credentials_options* options, bool send_client_ca_list);
|
543
|
+
extern grpc_tls_credentials_options_set_send_client_ca_list_type grpc_tls_credentials_options_set_send_client_ca_list_import;
|
544
|
+
#define grpc_tls_credentials_options_set_send_client_ca_list grpc_tls_credentials_options_set_send_client_ca_list_import
|
542
545
|
typedef void(*grpc_tls_credentials_options_set_check_call_host_type)(grpc_tls_credentials_options* options, int check_call_host);
|
543
546
|
extern grpc_tls_credentials_options_set_check_call_host_type grpc_tls_credentials_options_set_check_call_host_import;
|
544
547
|
#define grpc_tls_credentials_options_set_check_call_host grpc_tls_credentials_options_set_check_call_host_import
|
@@ -106,10 +106,7 @@ static void grpc_rb_server_free_internal(void* p) {
|
|
106
106
|
}
|
107
107
|
|
108
108
|
/* Destroys server instances. */
|
109
|
-
static void grpc_rb_server_free(void* p) {
|
110
|
-
grpc_rb_server_free_internal(p);
|
111
|
-
grpc_ruby_shutdown();
|
112
|
-
}
|
109
|
+
static void grpc_rb_server_free(void* p) { grpc_rb_server_free_internal(p); }
|
113
110
|
|
114
111
|
static const rb_data_type_t grpc_rb_server_data_type = {
|
115
112
|
"grpc_server",
|
@@ -155,10 +152,7 @@ static VALUE grpc_rb_server_init(VALUE self, VALUE channel_args) {
|
|
155
152
|
wrapper);
|
156
153
|
grpc_rb_hash_convert_to_channel_args(channel_args, &args);
|
157
154
|
srv = grpc_server_create(&args, NULL);
|
158
|
-
|
159
|
-
if (args.args != NULL) {
|
160
|
-
xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */
|
161
|
-
}
|
155
|
+
grpc_rb_channel_args_destroy(&args);
|
162
156
|
if (srv == NULL) {
|
163
157
|
rb_raise(rb_eRuntimeError, "could not create a gRPC server, not sure why");
|
164
158
|
}
|
@@ -191,65 +185,88 @@ static void grpc_request_call_stack_cleanup(request_call_stack* st) {
|
|
191
185
|
grpc_call_details_destroy(&st->details);
|
192
186
|
}
|
193
187
|
|
194
|
-
|
195
|
-
|
188
|
+
struct server_request_call_args {
|
189
|
+
grpc_rb_server* server;
|
190
|
+
grpc_completion_queue* call_queue;
|
191
|
+
request_call_stack st;
|
192
|
+
};
|
193
|
+
|
194
|
+
static VALUE grpc_rb_server_request_call_try(VALUE value_args) {
|
195
|
+
grpc_rb_fork_unsafe_begin();
|
196
|
+
struct server_request_call_args* args =
|
197
|
+
(struct server_request_call_args*)value_args;
|
196
198
|
|
197
|
-
Requests notification of a new call on a server. */
|
198
|
-
static VALUE grpc_rb_server_request_call(VALUE self) {
|
199
|
-
grpc_rb_server* s = NULL;
|
200
199
|
grpc_call* call = NULL;
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
void* tag = (void*)&st;
|
206
|
-
grpc_completion_queue* call_queue =
|
207
|
-
grpc_completion_queue_create_for_pluck(NULL);
|
208
|
-
gpr_timespec deadline;
|
200
|
+
void* tag = (void*)&args->st;
|
201
|
+
|
202
|
+
args->call_queue = grpc_completion_queue_create_for_pluck(NULL);
|
203
|
+
grpc_request_call_stack_init(&args->st);
|
209
204
|
|
210
|
-
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
211
|
-
if (s->wrapped == NULL) {
|
212
|
-
rb_raise(rb_eRuntimeError, "destroyed!");
|
213
|
-
return Qnil;
|
214
|
-
}
|
215
|
-
grpc_request_call_stack_init(&st);
|
216
205
|
/* call grpc_server_request_call, then wait for it to complete using
|
217
206
|
* pluck_event */
|
218
|
-
err = grpc_server_request_call(
|
219
|
-
|
207
|
+
grpc_call_error err = grpc_server_request_call(
|
208
|
+
args->server->wrapped, &call, &args->st.details, &args->st.md_ary,
|
209
|
+
args->call_queue, args->server->queue, tag);
|
220
210
|
if (err != GRPC_CALL_OK) {
|
221
|
-
grpc_request_call_stack_cleanup(&st);
|
222
211
|
rb_raise(grpc_rb_eCallError,
|
223
212
|
"grpc_server_request_call failed: %s (code=%d)",
|
224
213
|
grpc_call_error_detail_of(err), err);
|
225
|
-
return Qnil;
|
226
214
|
}
|
227
215
|
|
228
|
-
ev = rb_completion_queue_pluck(
|
229
|
-
|
216
|
+
grpc_event ev = rb_completion_queue_pluck(
|
217
|
+
args->server->queue, tag, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
230
218
|
if (!ev.success) {
|
231
|
-
grpc_request_call_stack_cleanup(&st);
|
232
219
|
rb_raise(grpc_rb_eCallError, "request_call completion failed");
|
233
|
-
return Qnil;
|
234
220
|
}
|
235
221
|
|
236
222
|
/* build the NewServerRpc struct result */
|
237
|
-
deadline =
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
223
|
+
gpr_timespec deadline =
|
224
|
+
gpr_convert_clock_type(args->st.details.deadline, GPR_CLOCK_REALTIME);
|
225
|
+
VALUE result =
|
226
|
+
rb_struct_new(grpc_rb_sNewServerRpc,
|
227
|
+
grpc_rb_slice_to_ruby_string(args->st.details.method),
|
228
|
+
grpc_rb_slice_to_ruby_string(args->st.details.host),
|
229
|
+
rb_funcall(rb_cTime, id_at, 2, INT2NUM(deadline.tv_sec),
|
230
|
+
INT2NUM(deadline.tv_nsec / 1000)),
|
231
|
+
grpc_rb_md_ary_to_h(&args->st.md_ary),
|
232
|
+
grpc_rb_wrap_call(call, args->call_queue), NULL);
|
233
|
+
args->call_queue = NULL;
|
246
234
|
return result;
|
247
235
|
}
|
248
236
|
|
237
|
+
static VALUE grpc_rb_server_request_call_ensure(VALUE value_args) {
|
238
|
+
grpc_rb_fork_unsafe_end();
|
239
|
+
struct server_request_call_args* args =
|
240
|
+
(struct server_request_call_args*)value_args;
|
241
|
+
|
242
|
+
if (args->call_queue) {
|
243
|
+
grpc_rb_completion_queue_destroy(args->call_queue);
|
244
|
+
}
|
245
|
+
|
246
|
+
grpc_request_call_stack_cleanup(&args->st);
|
247
|
+
|
248
|
+
return Qnil;
|
249
|
+
}
|
250
|
+
|
251
|
+
/* call-seq:
|
252
|
+
server.request_call
|
253
|
+
|
254
|
+
Requests notification of a new call on a server. */
|
255
|
+
static VALUE grpc_rb_server_request_call(VALUE self) {
|
256
|
+
grpc_rb_server* s;
|
257
|
+
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
258
|
+
grpc_ruby_fork_guard();
|
259
|
+
if (s->wrapped == NULL) {
|
260
|
+
rb_raise(rb_eRuntimeError, "destroyed!");
|
261
|
+
}
|
262
|
+
struct server_request_call_args args = {.server = s, .call_queue = NULL};
|
263
|
+
return rb_ensure(grpc_rb_server_request_call_try, (VALUE)&args,
|
264
|
+
grpc_rb_server_request_call_ensure, (VALUE)&args);
|
265
|
+
}
|
266
|
+
|
249
267
|
static VALUE grpc_rb_server_start(VALUE self) {
|
250
268
|
grpc_rb_server* s = NULL;
|
251
269
|
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
|
252
|
-
|
253
270
|
grpc_ruby_fork_guard();
|
254
271
|
if (s->wrapped == NULL) {
|
255
272
|
rb_raise(rb_eRuntimeError, "destroyed!");
|
@@ -62,7 +62,6 @@ static void grpc_rb_server_credentials_free_internal(void* p) {
|
|
62
62
|
/* Destroys the server credentials instances. */
|
63
63
|
static void grpc_rb_server_credentials_free(void* p) {
|
64
64
|
grpc_rb_server_credentials_free_internal(p);
|
65
|
-
grpc_ruby_shutdown();
|
66
65
|
}
|
67
66
|
|
68
67
|
/* Protects the mark object from GC */
|
@@ -62,7 +62,6 @@ static void grpc_rb_xds_channel_credentials_free_internal(void* p) {
|
|
62
62
|
/* Destroys the credentials instances. */
|
63
63
|
static void grpc_rb_xds_channel_credentials_free(void* p) {
|
64
64
|
grpc_rb_xds_channel_credentials_free_internal(p);
|
65
|
-
grpc_ruby_shutdown();
|
66
65
|
}
|
67
66
|
|
68
67
|
/* Protects the mark object from GC */
|
@@ -63,7 +63,6 @@ static void grpc_rb_xds_server_credentials_free_internal(void* p) {
|
|
63
63
|
/* Destroys the server credentials instances. */
|
64
64
|
static void grpc_rb_xds_server_credentials_free(void* p) {
|
65
65
|
grpc_rb_xds_server_credentials_free_internal(p);
|
66
|
-
grpc_ruby_shutdown();
|
67
66
|
}
|
68
67
|
|
69
68
|
/* Protects the mark object from GC */
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|