grpc 1.60.0.pre1-aarch64-linux
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/etc/roots.pem +4337 -0
- data/grpc_c.32-msvcrt.ruby +0 -0
- data/grpc_c.64-msvcrt.ruby +0 -0
- data/grpc_c.64-ucrt.ruby +0 -0
- data/src/ruby/bin/math_client.rb +140 -0
- data/src/ruby/bin/math_pb.rb +40 -0
- data/src/ruby/bin/math_server.rb +191 -0
- data/src/ruby/bin/math_services_pb.rb +51 -0
- data/src/ruby/bin/noproto_client.rb +93 -0
- data/src/ruby/bin/noproto_server.rb +97 -0
- 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.clang +1 -0
- data/src/ruby/ext/grpc/ext-export.gcc +6 -0
- data/src/ruby/ext/grpc/extconf.rb +270 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.c +65 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.h +35 -0
- data/src/ruby/ext/grpc/rb_call.c +1075 -0
- data/src/ruby/ext/grpc/rb_call.h +57 -0
- data/src/ruby/ext/grpc/rb_call_credentials.c +340 -0
- data/src/ruby/ext/grpc/rb_call_credentials.h +31 -0
- data/src/ruby/ext/grpc/rb_channel.c +875 -0
- data/src/ruby/ext/grpc/rb_channel.h +35 -0
- data/src/ruby/ext/grpc/rb_channel_args.c +172 -0
- data/src/ruby/ext/grpc/rb_channel_args.h +42 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.c +285 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.h +37 -0
- data/src/ruby/ext/grpc/rb_completion_queue.c +101 -0
- data/src/ruby/ext/grpc/rb_completion_queue.h +36 -0
- data/src/ruby/ext/grpc/rb_compression_options.c +470 -0
- data/src/ruby/ext/grpc/rb_compression_options.h +29 -0
- data/src/ruby/ext/grpc/rb_enable_cpp.cc +22 -0
- data/src/ruby/ext/grpc/rb_event_thread.c +161 -0
- data/src/ruby/ext/grpc/rb_event_thread.h +22 -0
- data/src/ruby/ext/grpc/rb_grpc.c +496 -0
- data/src/ruby/ext/grpc/rb_grpc.h +83 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +603 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +910 -0
- data/src/ruby/ext/grpc/rb_loader.c +61 -0
- data/src/ruby/ext/grpc/rb_loader.h +25 -0
- data/src/ruby/ext/grpc/rb_server.c +405 -0
- data/src/ruby/ext/grpc/rb_server.h +32 -0
- data/src/ruby/ext/grpc/rb_server_credentials.c +258 -0
- data/src/ruby/ext/grpc/rb_server_credentials.h +37 -0
- data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +217 -0
- data/src/ruby/ext/grpc/rb_xds_channel_credentials.h +37 -0
- data/src/ruby/ext/grpc/rb_xds_server_credentials.c +169 -0
- data/src/ruby/ext/grpc/rb_xds_server_credentials.h +37 -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/core/status_codes.rb +135 -0
- data/src/ruby/lib/grpc/core/time_consts.rb +56 -0
- data/src/ruby/lib/grpc/errors.rb +277 -0
- data/src/ruby/lib/grpc/generic/active_call.rb +670 -0
- data/src/ruby/lib/grpc/generic/bidi_call.rb +237 -0
- data/src/ruby/lib/grpc/generic/client_stub.rb +503 -0
- data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
- data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
- data/src/ruby/lib/grpc/generic/rpc_desc.rb +204 -0
- data/src/ruby/lib/grpc/generic/rpc_server.rb +551 -0
- data/src/ruby/lib/grpc/generic/service.rb +211 -0
- data/src/ruby/lib/grpc/google_rpc_status_utils.rb +40 -0
- data/src/ruby/lib/grpc/grpc.rb +24 -0
- data/src/ruby/lib/grpc/logconfig.rb +44 -0
- data/src/ruby/lib/grpc/notifier.rb +45 -0
- data/src/ruby/lib/grpc/structs.rb +15 -0
- data/src/ruby/lib/grpc/version.rb +18 -0
- data/src/ruby/lib/grpc.rb +37 -0
- data/src/ruby/pb/README.md +42 -0
- data/src/ruby/pb/generate_proto_ruby.sh +46 -0
- data/src/ruby/pb/grpc/health/checker.rb +75 -0
- data/src/ruby/pb/grpc/health/v1/health_pb.rb +42 -0
- data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +62 -0
- data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +44 -0
- data/src/ruby/pb/grpc/testing/metrics_pb.rb +28 -0
- data/src/ruby/pb/grpc/testing/metrics_services_pb.rb +49 -0
- data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +38 -0
- data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +71 -0
- data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +40 -0
- data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +174 -0
- data/src/ruby/pb/test/client.rb +785 -0
- data/src/ruby/pb/test/server.rb +252 -0
- data/src/ruby/pb/test/xds_client.rb +415 -0
- data/src/ruby/spec/call_credentials_spec.rb +42 -0
- data/src/ruby/spec/call_spec.rb +180 -0
- data/src/ruby/spec/channel_connection_spec.rb +126 -0
- data/src/ruby/spec/channel_credentials_spec.rb +124 -0
- data/src/ruby/spec/channel_spec.rb +207 -0
- data/src/ruby/spec/client_auth_spec.rb +152 -0
- data/src/ruby/spec/client_server_spec.rb +676 -0
- data/src/ruby/spec/compression_options_spec.rb +149 -0
- data/src/ruby/spec/debug_message_spec.rb +134 -0
- data/src/ruby/spec/error_sanity_spec.rb +49 -0
- data/src/ruby/spec/errors_spec.rb +142 -0
- data/src/ruby/spec/generic/active_call_spec.rb +692 -0
- data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
- data/src/ruby/spec/generic/client_stub_spec.rb +1083 -0
- data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
- data/src/ruby/spec/generic/rpc_desc_spec.rb +374 -0
- data/src/ruby/spec/generic/rpc_server_pool_spec.rb +127 -0
- data/src/ruby/spec/generic/rpc_server_spec.rb +748 -0
- data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
- data/src/ruby/spec/generic/service_spec.rb +263 -0
- data/src/ruby/spec/google_rpc_status_utils_spec.rb +282 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/package_options.proto +28 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import.proto +22 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import2.proto +23 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +41 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/same_package_service_name.proto +27 -0
- data/src/ruby/spec/pb/codegen/grpc/testing/same_ruby_package_service_name.proto +29 -0
- data/src/ruby/spec/pb/codegen/package_option_spec.rb +98 -0
- data/src/ruby/spec/pb/duplicate/codegen_spec.rb +57 -0
- data/src/ruby/spec/pb/health/checker_spec.rb +236 -0
- data/src/ruby/spec/server_credentials_spec.rb +104 -0
- data/src/ruby/spec/server_spec.rb +231 -0
- data/src/ruby/spec/spec_helper.rb +61 -0
- data/src/ruby/spec/support/helpers.rb +107 -0
- data/src/ruby/spec/support/services.rb +160 -0
- data/src/ruby/spec/testdata/README +1 -0
- data/src/ruby/spec/testdata/ca.pem +20 -0
- data/src/ruby/spec/testdata/client.key +28 -0
- data/src/ruby/spec/testdata/client.pem +20 -0
- data/src/ruby/spec/testdata/server1.key +28 -0
- data/src/ruby/spec/testdata/server1.pem +22 -0
- data/src/ruby/spec/time_consts_spec.rb +74 -0
- data/src/ruby/spec/user_agent_spec.rb +74 -0
- metadata +405 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* Copyright 2016 gRPC authors.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include <ruby/ruby.h>
|
20
|
+
|
21
|
+
#include "rb_event_thread.h"
|
22
|
+
|
23
|
+
#include <ruby/thread.h>
|
24
|
+
#include <stdbool.h>
|
25
|
+
|
26
|
+
#include "rb_grpc.h"
|
27
|
+
#include "rb_grpc_imports.generated.h"
|
28
|
+
|
29
|
+
#include <grpc/support/alloc.h>
|
30
|
+
#include <grpc/support/log.h>
|
31
|
+
#include <grpc/support/sync.h>
|
32
|
+
#include <grpc/support/time.h>
|
33
|
+
|
34
|
+
typedef struct grpc_rb_event {
|
35
|
+
// callback will be called with argument while holding the GVL
|
36
|
+
void (*callback)(void*);
|
37
|
+
void* argument;
|
38
|
+
|
39
|
+
struct grpc_rb_event* next;
|
40
|
+
} grpc_rb_event;
|
41
|
+
|
42
|
+
typedef struct grpc_rb_event_queue {
|
43
|
+
grpc_rb_event* head;
|
44
|
+
grpc_rb_event* tail;
|
45
|
+
|
46
|
+
gpr_mu mu;
|
47
|
+
gpr_cv cv;
|
48
|
+
|
49
|
+
// Indicates that the thread should stop waiting
|
50
|
+
bool abort;
|
51
|
+
} grpc_rb_event_queue;
|
52
|
+
|
53
|
+
static grpc_rb_event_queue event_queue;
|
54
|
+
static VALUE g_event_thread = Qnil;
|
55
|
+
static bool g_one_time_init_done = false;
|
56
|
+
|
57
|
+
void grpc_rb_event_queue_enqueue(void (*callback)(void*), void* argument) {
|
58
|
+
grpc_rb_event* event = gpr_malloc(sizeof(grpc_rb_event));
|
59
|
+
event->callback = callback;
|
60
|
+
event->argument = argument;
|
61
|
+
event->next = NULL;
|
62
|
+
gpr_mu_lock(&event_queue.mu);
|
63
|
+
if (event_queue.tail == NULL) {
|
64
|
+
event_queue.head = event_queue.tail = event;
|
65
|
+
} else {
|
66
|
+
event_queue.tail->next = event;
|
67
|
+
event_queue.tail = event;
|
68
|
+
}
|
69
|
+
gpr_cv_signal(&event_queue.cv);
|
70
|
+
gpr_mu_unlock(&event_queue.mu);
|
71
|
+
}
|
72
|
+
|
73
|
+
static grpc_rb_event* grpc_rb_event_queue_dequeue() {
|
74
|
+
grpc_rb_event* event;
|
75
|
+
if (event_queue.head == NULL) {
|
76
|
+
event = NULL;
|
77
|
+
} else {
|
78
|
+
event = event_queue.head;
|
79
|
+
if (event_queue.head->next == NULL) {
|
80
|
+
event_queue.head = event_queue.tail = NULL;
|
81
|
+
} else {
|
82
|
+
event_queue.head = event_queue.head->next;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
return event;
|
86
|
+
}
|
87
|
+
|
88
|
+
static void grpc_rb_event_queue_destroy() {
|
89
|
+
gpr_mu_destroy(&event_queue.mu);
|
90
|
+
gpr_cv_destroy(&event_queue.cv);
|
91
|
+
}
|
92
|
+
|
93
|
+
static void* grpc_rb_wait_for_event_no_gil(void* param) {
|
94
|
+
grpc_rb_event* event = NULL;
|
95
|
+
(void)param;
|
96
|
+
gpr_mu_lock(&event_queue.mu);
|
97
|
+
while (!event_queue.abort) {
|
98
|
+
if ((event = grpc_rb_event_queue_dequeue()) != NULL) {
|
99
|
+
gpr_mu_unlock(&event_queue.mu);
|
100
|
+
return event;
|
101
|
+
}
|
102
|
+
gpr_cv_wait(&event_queue.cv, &event_queue.mu,
|
103
|
+
gpr_inf_future(GPR_CLOCK_REALTIME));
|
104
|
+
}
|
105
|
+
gpr_mu_unlock(&event_queue.mu);
|
106
|
+
return NULL;
|
107
|
+
}
|
108
|
+
|
109
|
+
static void grpc_rb_event_unblocking_func(void* arg) {
|
110
|
+
(void)arg;
|
111
|
+
gpr_mu_lock(&event_queue.mu);
|
112
|
+
event_queue.abort = true;
|
113
|
+
gpr_cv_signal(&event_queue.cv);
|
114
|
+
gpr_mu_unlock(&event_queue.mu);
|
115
|
+
}
|
116
|
+
|
117
|
+
/* This is the implementation of the thread that handles auth metadata plugin
|
118
|
+
* events */
|
119
|
+
static VALUE grpc_rb_event_thread(VALUE arg) {
|
120
|
+
grpc_rb_event* event;
|
121
|
+
(void)arg;
|
122
|
+
while (true) {
|
123
|
+
event = (grpc_rb_event*)rb_thread_call_without_gvl(
|
124
|
+
grpc_rb_wait_for_event_no_gil, NULL, grpc_rb_event_unblocking_func,
|
125
|
+
NULL);
|
126
|
+
if (event == NULL) {
|
127
|
+
// Indicates that the thread needs to shut down
|
128
|
+
break;
|
129
|
+
} else {
|
130
|
+
event->callback(event->argument);
|
131
|
+
gpr_free(event);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
grpc_rb_event_queue_destroy();
|
135
|
+
return Qnil;
|
136
|
+
}
|
137
|
+
|
138
|
+
void grpc_rb_event_queue_thread_start() {
|
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
|
+
}
|
146
|
+
event_queue.abort = false;
|
147
|
+
GPR_ASSERT(!RTEST(g_event_thread));
|
148
|
+
g_event_thread = rb_thread_create(grpc_rb_event_thread, NULL);
|
149
|
+
}
|
150
|
+
|
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;
|
161
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* Copyright 2016 gRPC authors.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*
|
17
|
+
*/
|
18
|
+
|
19
|
+
void grpc_rb_event_queue_thread_start();
|
20
|
+
void grpc_rb_event_queue_thread_stop();
|
21
|
+
|
22
|
+
void grpc_rb_event_queue_enqueue(void (*callback)(void*), void* argument);
|
@@ -0,0 +1,496 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* Copyright 2015 gRPC authors.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include <ruby/ruby.h>
|
20
|
+
|
21
|
+
#include "rb_grpc.h"
|
22
|
+
|
23
|
+
#include <math.h>
|
24
|
+
#include <ruby/vm.h>
|
25
|
+
#include <stdbool.h>
|
26
|
+
#include <sys/time.h>
|
27
|
+
#include <sys/types.h>
|
28
|
+
#include <unistd.h>
|
29
|
+
|
30
|
+
#include "rb_call.h"
|
31
|
+
#include "rb_call_credentials.h"
|
32
|
+
#include "rb_channel.h"
|
33
|
+
#include "rb_channel_credentials.h"
|
34
|
+
#include "rb_compression_options.h"
|
35
|
+
#include "rb_event_thread.h"
|
36
|
+
#include "rb_grpc_imports.generated.h"
|
37
|
+
#include "rb_loader.h"
|
38
|
+
#include "rb_server.h"
|
39
|
+
#include "rb_server_credentials.h"
|
40
|
+
#include "rb_xds_channel_credentials.h"
|
41
|
+
#include "rb_xds_server_credentials.h"
|
42
|
+
|
43
|
+
#include <grpc/grpc.h>
|
44
|
+
#include <grpc/support/log.h>
|
45
|
+
#include <grpc/support/time.h>
|
46
|
+
|
47
|
+
#ifdef GPR_LINUX
|
48
|
+
#include <sys/syscall.h>
|
49
|
+
#include <unistd.h>
|
50
|
+
#endif
|
51
|
+
|
52
|
+
static VALUE grpc_rb_cTimeVal = Qnil;
|
53
|
+
|
54
|
+
static rb_data_type_t grpc_rb_timespec_data_type = {
|
55
|
+
"gpr_timespec",
|
56
|
+
{GRPC_RB_GC_NOT_MARKED,
|
57
|
+
GRPC_RB_GC_DONT_FREE,
|
58
|
+
GRPC_RB_MEMSIZE_UNAVAILABLE,
|
59
|
+
{NULL, NULL}},
|
60
|
+
NULL,
|
61
|
+
NULL,
|
62
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
63
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
64
|
+
#endif
|
65
|
+
};
|
66
|
+
|
67
|
+
/* Alloc func that blocks allocation of a given object by raising an
|
68
|
+
* exception. */
|
69
|
+
VALUE grpc_rb_cannot_alloc(VALUE cls) {
|
70
|
+
rb_raise(rb_eTypeError,
|
71
|
+
"allocation of %s only allowed from the gRPC native layer",
|
72
|
+
rb_class2name(cls));
|
73
|
+
return Qnil;
|
74
|
+
}
|
75
|
+
|
76
|
+
/* Init func that fails by raising an exception. */
|
77
|
+
VALUE grpc_rb_cannot_init(VALUE self) {
|
78
|
+
rb_raise(rb_eTypeError,
|
79
|
+
"initialization of %s only allowed from the gRPC native layer",
|
80
|
+
rb_obj_classname(self));
|
81
|
+
return Qnil;
|
82
|
+
}
|
83
|
+
|
84
|
+
/* Init/Clone func that fails by raising an exception. */
|
85
|
+
VALUE grpc_rb_cannot_init_copy(VALUE copy, VALUE self) {
|
86
|
+
(void)self;
|
87
|
+
rb_raise(rb_eTypeError, "Copy initialization of %s is not supported",
|
88
|
+
rb_obj_classname(copy));
|
89
|
+
return Qnil;
|
90
|
+
}
|
91
|
+
|
92
|
+
/* id_tv_{,u}sec are accessor methods on Ruby Time instances. */
|
93
|
+
static ID id_tv_sec;
|
94
|
+
static ID id_tv_nsec;
|
95
|
+
|
96
|
+
/**
|
97
|
+
* grpc_rb_time_timeval creates a timeval from a ruby time object.
|
98
|
+
*
|
99
|
+
* This func is copied from ruby source, MRI/source/time.c, which is published
|
100
|
+
* under the same license as the ruby.h, on which the entire extensions is
|
101
|
+
* based.
|
102
|
+
*/
|
103
|
+
gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) {
|
104
|
+
gpr_timespec t;
|
105
|
+
gpr_timespec* time_const;
|
106
|
+
const char* tstr = interval ? "time interval" : "time";
|
107
|
+
const char* want = " want <secs from epoch>|<Time>|<GRPC::TimeConst.*>";
|
108
|
+
|
109
|
+
t.clock_type = GPR_CLOCK_REALTIME;
|
110
|
+
switch (TYPE(time)) {
|
111
|
+
case T_DATA:
|
112
|
+
if (CLASS_OF(time) == grpc_rb_cTimeVal) {
|
113
|
+
TypedData_Get_Struct(time, gpr_timespec, &grpc_rb_timespec_data_type,
|
114
|
+
time_const);
|
115
|
+
t = *time_const;
|
116
|
+
} else if (CLASS_OF(time) == rb_cTime) {
|
117
|
+
t.tv_sec = NUM2INT(rb_funcall(time, id_tv_sec, 0));
|
118
|
+
t.tv_nsec = NUM2INT(rb_funcall(time, id_tv_nsec, 0));
|
119
|
+
} else {
|
120
|
+
rb_raise(rb_eTypeError, "bad input: (%s)->c_timeval, got <%s>,%s", tstr,
|
121
|
+
rb_obj_classname(time), want);
|
122
|
+
}
|
123
|
+
break;
|
124
|
+
|
125
|
+
case T_FIXNUM:
|
126
|
+
t.tv_sec = FIX2LONG(time);
|
127
|
+
if (interval && t.tv_sec < 0)
|
128
|
+
rb_raise(rb_eArgError, "%s must be positive", tstr);
|
129
|
+
t.tv_nsec = 0;
|
130
|
+
break;
|
131
|
+
|
132
|
+
case T_FLOAT:
|
133
|
+
if (interval && RFLOAT_VALUE(time) < 0.0)
|
134
|
+
rb_raise(rb_eArgError, "%s must be positive", tstr);
|
135
|
+
else {
|
136
|
+
double f, d;
|
137
|
+
|
138
|
+
d = modf(RFLOAT_VALUE(time), &f);
|
139
|
+
if (d < 0) {
|
140
|
+
d += 1;
|
141
|
+
f -= 1;
|
142
|
+
}
|
143
|
+
t.tv_sec = (int64_t)f;
|
144
|
+
if (f != t.tv_sec) {
|
145
|
+
rb_raise(rb_eRangeError, "%f out of Time range", RFLOAT_VALUE(time));
|
146
|
+
}
|
147
|
+
t.tv_nsec = (int)(d * 1e9 + 0.5);
|
148
|
+
}
|
149
|
+
break;
|
150
|
+
|
151
|
+
case T_BIGNUM:
|
152
|
+
t.tv_sec = NUM2LONG(time);
|
153
|
+
if (interval && t.tv_sec < 0)
|
154
|
+
rb_raise(rb_eArgError, "%s must be positive", tstr);
|
155
|
+
t.tv_nsec = 0;
|
156
|
+
break;
|
157
|
+
|
158
|
+
default:
|
159
|
+
rb_raise(rb_eTypeError, "bad input: (%s)->c_timeval, got <%s>,%s", tstr,
|
160
|
+
rb_obj_classname(time), want);
|
161
|
+
break;
|
162
|
+
}
|
163
|
+
return t;
|
164
|
+
}
|
165
|
+
|
166
|
+
/* id_at is the constructor method of the ruby standard Time class. */
|
167
|
+
static ID id_at;
|
168
|
+
|
169
|
+
/* id_inspect is the inspect method found on various ruby objects. */
|
170
|
+
static ID id_inspect;
|
171
|
+
|
172
|
+
/* id_to_s is the to_s method found on various ruby objects. */
|
173
|
+
static ID id_to_s;
|
174
|
+
|
175
|
+
/* Converts a wrapped time constant to a standard time. */
|
176
|
+
static VALUE grpc_rb_time_val_to_time(VALUE self) {
|
177
|
+
gpr_timespec* time_const = NULL;
|
178
|
+
gpr_timespec real_time;
|
179
|
+
TypedData_Get_Struct(self, gpr_timespec, &grpc_rb_timespec_data_type,
|
180
|
+
time_const);
|
181
|
+
real_time = gpr_convert_clock_type(*time_const, GPR_CLOCK_REALTIME);
|
182
|
+
return rb_funcall(rb_cTime, id_at, 2, INT2NUM(real_time.tv_sec),
|
183
|
+
INT2NUM(real_time.tv_nsec / 1000));
|
184
|
+
}
|
185
|
+
|
186
|
+
/* Invokes inspect on the ctime version of the time val. */
|
187
|
+
static VALUE grpc_rb_time_val_inspect(VALUE self) {
|
188
|
+
return rb_funcall(grpc_rb_time_val_to_time(self), id_inspect, 0);
|
189
|
+
}
|
190
|
+
|
191
|
+
/* Invokes to_s on the ctime version of the time val. */
|
192
|
+
static VALUE grpc_rb_time_val_to_s(VALUE self) {
|
193
|
+
return rb_funcall(grpc_rb_time_val_to_time(self), id_to_s, 0);
|
194
|
+
}
|
195
|
+
|
196
|
+
static gpr_timespec zero_realtime;
|
197
|
+
static gpr_timespec inf_future_realtime;
|
198
|
+
static gpr_timespec inf_past_realtime;
|
199
|
+
|
200
|
+
/* Adds a module with constants that map to gpr's static timeval structs. */
|
201
|
+
static void Init_grpc_time_consts() {
|
202
|
+
VALUE grpc_rb_mTimeConsts =
|
203
|
+
rb_define_module_under(grpc_rb_mGrpcCore, "TimeConsts");
|
204
|
+
grpc_rb_cTimeVal =
|
205
|
+
rb_define_class_under(grpc_rb_mGrpcCore, "TimeSpec", rb_cObject);
|
206
|
+
rb_undef_alloc_func(grpc_rb_cTimeVal);
|
207
|
+
zero_realtime = gpr_time_0(GPR_CLOCK_REALTIME);
|
208
|
+
inf_future_realtime = gpr_inf_future(GPR_CLOCK_REALTIME);
|
209
|
+
inf_past_realtime = gpr_inf_past(GPR_CLOCK_REALTIME);
|
210
|
+
rb_define_const(
|
211
|
+
grpc_rb_mTimeConsts, "ZERO",
|
212
|
+
TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
|
213
|
+
(void*)&zero_realtime));
|
214
|
+
rb_define_const(
|
215
|
+
grpc_rb_mTimeConsts, "INFINITE_FUTURE",
|
216
|
+
TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
|
217
|
+
(void*)&inf_future_realtime));
|
218
|
+
rb_define_const(
|
219
|
+
grpc_rb_mTimeConsts, "INFINITE_PAST",
|
220
|
+
TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
|
221
|
+
(void*)&inf_past_realtime));
|
222
|
+
rb_define_method(grpc_rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0);
|
223
|
+
rb_define_method(grpc_rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0);
|
224
|
+
rb_define_method(grpc_rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0);
|
225
|
+
id_at = rb_intern("at");
|
226
|
+
id_inspect = rb_intern("inspect");
|
227
|
+
id_to_s = rb_intern("to_s");
|
228
|
+
id_tv_sec = rb_intern("tv_sec");
|
229
|
+
id_tv_nsec = rb_intern("tv_nsec");
|
230
|
+
}
|
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
|
+
|
242
|
+
#if GPR_WINDOWS
|
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) {}
|
247
|
+
#else
|
248
|
+
static pid_t g_init_pid;
|
249
|
+
static long g_init_tid;
|
250
|
+
|
251
|
+
static bool grpc_ruby_initial_pid(void) {
|
252
|
+
GPR_ASSERT(g_init_pid != 0);
|
253
|
+
return g_init_pid == getpid();
|
254
|
+
}
|
255
|
+
|
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
|
+
}
|
277
|
+
}
|
278
|
+
#endif
|
279
|
+
|
280
|
+
/* Initialize the GRPC module structs */
|
281
|
+
|
282
|
+
/* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */
|
283
|
+
VALUE grpc_rb_sNewServerRpc = Qnil;
|
284
|
+
/* grpc_rb_sStatus is the struct that holds status details. */
|
285
|
+
VALUE grpc_rb_sStatus = Qnil;
|
286
|
+
|
287
|
+
/* Initialize the GRPC module. */
|
288
|
+
VALUE grpc_rb_mGRPC = Qnil;
|
289
|
+
VALUE grpc_rb_mGrpcCore = Qnil;
|
290
|
+
|
291
|
+
/* cached Symbols for members in Status struct */
|
292
|
+
VALUE sym_code = Qundef;
|
293
|
+
VALUE sym_details = Qundef;
|
294
|
+
VALUE sym_metadata = Qundef;
|
295
|
+
|
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
|
299
|
+
|
300
|
+
void grpc_ruby_fork_guard() {
|
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
|
+
}
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
static VALUE g_bg_thread_init_rb_mu = Qundef;
|
325
|
+
static bool g_bg_thread_init_done;
|
326
|
+
|
327
|
+
static void grpc_ruby_init_threads() {
|
328
|
+
// Avoid calling into ruby library (when creating threads here)
|
329
|
+
// in gpr_once_init. In general, it appears to be unsafe to call
|
330
|
+
// into the ruby library while holding a non-ruby mutex, because a gil yield
|
331
|
+
// could end up trying to lock onto that same mutex and deadlocking.
|
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) {
|
337
|
+
grpc_rb_event_queue_thread_start();
|
338
|
+
grpc_rb_channel_polling_thread_start();
|
339
|
+
g_bg_thread_init_done = true;
|
340
|
+
}
|
341
|
+
rb_mutex_unlock(g_bg_thread_init_rb_mu);
|
342
|
+
}
|
343
|
+
|
344
|
+
static int64_t g_grpc_ruby_init_count;
|
345
|
+
|
346
|
+
void grpc_ruby_init() {
|
347
|
+
gpr_once_init(&g_once_init, grpc_ruby_basic_init);
|
348
|
+
grpc_ruby_fork_guard();
|
349
|
+
grpc_init();
|
350
|
+
grpc_ruby_init_threads();
|
351
|
+
// (only gpr_log after logging has been initialized)
|
352
|
+
gpr_log(GPR_DEBUG,
|
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;
|
406
|
+
}
|
407
|
+
|
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;
|
423
|
+
}
|
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
|
458
|
+
void Init_grpc_c() {
|
459
|
+
if (!grpc_rb_load_core()) {
|
460
|
+
rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
|
461
|
+
return;
|
462
|
+
}
|
463
|
+
|
464
|
+
rb_global_variable(&g_bg_thread_init_rb_mu);
|
465
|
+
g_bg_thread_init_rb_mu = rb_mutex_new();
|
466
|
+
|
467
|
+
grpc_rb_mGRPC = rb_define_module("GRPC");
|
468
|
+
grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
|
469
|
+
grpc_rb_sNewServerRpc = rb_struct_define(
|
470
|
+
"NewServerRpc", "method", "host", "deadline", "metadata", "call", NULL);
|
471
|
+
grpc_rb_sStatus = rb_const_get(rb_cStruct, rb_intern("Status"));
|
472
|
+
sym_code = ID2SYM(rb_intern("code"));
|
473
|
+
sym_details = ID2SYM(rb_intern("details"));
|
474
|
+
sym_metadata = ID2SYM(rb_intern("metadata"));
|
475
|
+
// init C-defined classes
|
476
|
+
Init_grpc_channel();
|
477
|
+
Init_grpc_call();
|
478
|
+
Init_grpc_call_credentials();
|
479
|
+
Init_grpc_channel_credentials();
|
480
|
+
Init_grpc_xds_channel_credentials();
|
481
|
+
Init_grpc_server();
|
482
|
+
Init_grpc_server_credentials();
|
483
|
+
Init_grpc_xds_server_credentials();
|
484
|
+
Init_grpc_time_consts();
|
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);
|
496
|
+
}
|