Skip to content

Commit 463682d

Browse files
authored
GH-50302: [GLib][Ruby][FlightRPC] Fix GC related problems (#50401)
### Rationale for this change `gaflight_server_listen()` may use options' auth handler later. So we should refer the given options while the server is alive. If we don't refer the given options, we may touch freed auth handler later. The argument of `ArrowFlight::Criteria.new`/`ArrowFlight::Ticket.new` should be referred to protect from GC in Ruby. I could fix some problems by `GC.stress = true` but I couldn't fix some problems that are reproduced only on GitHub Actions. I omit tests for them for now. ### What changes are included in this PR? * Refer options for `gaflight_server_listen()` * Refer expression for `ArrowFlight::Criteria.new` * Refer data for `ArrowFlight::Ticket.new` * Omit Flight related tests that I can't fix... ### Are these changes tested? Yes. ### Are there any user-facing changes? Yes. * GitHub Issue: #50302 Authored-by: Sutou Kouhei <kou@clear-code.com> Signed-off-by: Sutou Kouhei <kou@clear-code.com>
1 parent 2f5384f commit 463682d

20 files changed

Lines changed: 190 additions & 22 deletions

File tree

c_glib/arrow-flight-glib/server.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ G_BEGIN_DECLS
11661166
struct GAFlightServerPrivate
11671167
{
11681168
gaflight::Server server;
1169+
GAFlightServerOptions *options;
11691170
};
11701171

11711172
G_END_DECLS
@@ -1179,6 +1180,10 @@ gaflight_server_servable_interface_init(GAFlightServableInterface *iface)
11791180
iface->get_raw = gaflight_server_servable_get_raw;
11801181
}
11811182

1183+
enum {
1184+
PROP_OPTIONS = 1,
1185+
};
1186+
11821187
G_DEFINE_ABSTRACT_TYPE_WITH_CODE(
11831188
GAFlightServer, gaflight_server, G_TYPE_OBJECT, G_ADD_PRIVATE(GAFlightServer);
11841189
G_IMPLEMENT_INTERFACE(GAFLIGHT_TYPE_SERVABLE, gaflight_server_servable_interface_init))
@@ -1196,6 +1201,19 @@ gaflight_server_servable_get_raw(GAFlightServable *servable)
11961201
}
11971202
G_BEGIN_DECLS
11981203

1204+
static void
1205+
gaflight_server_dispose(GObject *object)
1206+
{
1207+
auto priv = GAFLIGHT_SERVER_GET_PRIVATE(object);
1208+
1209+
if (priv->options) {
1210+
g_object_unref(priv->options);
1211+
priv->options = nullptr;
1212+
}
1213+
1214+
G_OBJECT_CLASS(gaflight_server_parent_class)->dispose(object);
1215+
}
1216+
11991217
static void
12001218
gaflight_server_finalize(GObject *object)
12011219
{
@@ -1205,6 +1223,24 @@ gaflight_server_finalize(GObject *object)
12051223
G_OBJECT_CLASS(gaflight_server_parent_class)->finalize(object);
12061224
}
12071225

1226+
static void
1227+
gaflight_server_get_property(GObject *object,
1228+
guint prop_id,
1229+
GValue *value,
1230+
GParamSpec *pspec)
1231+
{
1232+
auto priv = GAFLIGHT_SERVER_GET_PRIVATE(object);
1233+
1234+
switch (prop_id) {
1235+
case PROP_OPTIONS:
1236+
g_value_set_object(value, priv->options);
1237+
break;
1238+
default:
1239+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1240+
break;
1241+
}
1242+
}
1243+
12081244
static void
12091245
gaflight_server_init(GAFlightServer *object)
12101246
{
@@ -1216,7 +1252,24 @@ static void
12161252
gaflight_server_class_init(GAFlightServerClass *klass)
12171253
{
12181254
auto gobject_class = G_OBJECT_CLASS(klass);
1255+
gobject_class->dispose = gaflight_server_dispose;
12191256
gobject_class->finalize = gaflight_server_finalize;
1257+
gobject_class->get_property = gaflight_server_get_property;
1258+
1259+
GParamSpec *spec;
1260+
/**
1261+
* GAFlightServer:options:
1262+
*
1263+
* The options used in this server.
1264+
*
1265+
* Since: 26.0.0
1266+
*/
1267+
spec = g_param_spec_object("options",
1268+
"Options",
1269+
"The options used in this server",
1270+
GAFLIGHT_TYPE_SERVER_OPTIONS,
1271+
static_cast<GParamFlags>(G_PARAM_READABLE));
1272+
g_object_class_install_property(gobject_class, PROP_OPTIONS, spec);
12201273
}
12211274

12221275
/**
@@ -1236,6 +1289,14 @@ gaflight_server_listen(GAFlightServer *server,
12361289
{
12371290
auto flight_server = gaflight_servable_get_raw(GAFLIGHT_SERVABLE(server));
12381291
const auto flight_options = gaflight_server_options_get_raw(options);
1292+
auto priv = GAFLIGHT_SERVER_GET_PRIVATE(server);
1293+
if (priv->options != options) {
1294+
g_object_ref(options);
1295+
if (priv->options) {
1296+
g_object_unref(priv->options);
1297+
}
1298+
priv->options = options;
1299+
}
12391300
return garrow::check(error,
12401301
flight_server->Init(*flight_options),
12411302
"[flight-server][listen]");

c_glib/test/flight/test-client.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def setup
2222
@server = nil
2323
omit("Arrow Flight is required") unless defined?(ArrowFlight)
2424
omit("Unstable on Windows") if Gem.win_platform?
25-
omit("Unstable on x86_64 macOS") if /x86_64-darwin/.match?(RUBY_PLATFORM)
25+
omit("Unstable on macOS") if /darwin/.match?(RUBY_PLATFORM)
2626
require_gi_bindings(3, 4, 7)
2727
@server = Helper::FlightServer.new
2828
host = "127.0.0.1"
@@ -80,8 +80,9 @@ def test_success
8080

8181
def test_error
8282
client = ArrowFlight::Client.new(@location)
83+
invalid_data = GLib::Bytes.new("invalid")
8384
assert_raise(Arrow::Error::Invalid) do
84-
client.do_get(ArrowFlight::Ticket.new("invalid"))
85+
client.do_get(ArrowFlight::Ticket.new(invalid_data))
8586
end
8687
end
8788
end

c_glib/test/flight/test-criteria.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ def setup
2222

2323
def test_expression
2424
expression = "expression"
25-
criteria = ArrowFlight::Criteria.new(expression)
25+
expression_bytes = GLib::Bytes.new(expression)
26+
criteria = ArrowFlight::Criteria.new(expression_bytes)
2627
assert_equal(expression,
2728
criteria.expression.to_s)
2829
end

c_glib/test/flight/test-endpoint.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ def setup
2121
end
2222

2323
def test_ticket
24-
ticket = ArrowFlight::Ticket.new("data")
24+
data = GLib::Bytes.new("data")
25+
ticket = ArrowFlight::Ticket.new(data)
2526
locations = [
2627
ArrowFlight::Location.new("grpc://127.0.0.1:2929"),
2728
ArrowFlight::Location.new("grpc+tcp://127.0.0.1:12929"),
@@ -32,7 +33,8 @@ def test_ticket
3233
end
3334

3435
def test_locations
35-
ticket = ArrowFlight::Ticket.new("data")
36+
data = GLib::Bytes.new("data")
37+
ticket = ArrowFlight::Ticket.new(data)
3638
locations = [
3739
ArrowFlight::Location.new("grpc://127.0.0.1:2929"),
3840
ArrowFlight::Location.new("grpc+tcp://127.0.0.1:12929"),
@@ -44,7 +46,8 @@ def test_locations
4446

4547
sub_test_case("#==") do
4648
def test_true
47-
ticket = ArrowFlight::Ticket.new("data")
49+
data = GLib::Bytes.new("data")
50+
ticket = ArrowFlight::Ticket.new(data)
4851
location = ArrowFlight::Location.new("grpc://127.0.0.1:2929")
4952
endpoint1 = ArrowFlight::Endpoint.new(ticket, [location])
5053
endpoint2 = ArrowFlight::Endpoint.new(ticket, [location])
@@ -54,7 +57,8 @@ def test_true
5457
end
5558

5659
def test_false
57-
ticket = ArrowFlight::Ticket.new("data")
60+
data = GLib::Bytes.new("data")
61+
ticket = ArrowFlight::Ticket.new(data)
5862
location1 = ArrowFlight::Location.new("grpc://127.0.0.1:2929")
5963
location2 = ArrowFlight::Location.new("grpc://127.0.0.1:1129")
6064
endpoint1 = ArrowFlight::Endpoint.new(ticket, [location1])

c_glib/test/flight/test-ticket.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,28 @@ def setup
2222

2323
def test_data
2424
data = "data"
25-
ticket = ArrowFlight::Ticket.new(data)
25+
data_bytes = GLib::Bytes.new(data)
26+
ticket = ArrowFlight::Ticket.new(data_bytes)
2627
assert_equal(data,
2728
ticket.data.to_s)
2829
end
2930

3031
sub_test_case("#==") do
3132
def test_true
32-
ticket1 = ArrowFlight::Ticket.new("data")
33-
ticket2 = ArrowFlight::Ticket.new("data")
33+
data1 = GLib::Bytes.new("data")
34+
data2 = GLib::Bytes.new("data")
35+
ticket1 = ArrowFlight::Ticket.new(data1)
36+
ticket2 = ArrowFlight::Ticket.new(data2)
3437
assert do
3538
ticket1 == ticket2
3639
end
3740
end
3841

3942
def test_false
40-
ticket1 = ArrowFlight::Ticket.new("data1")
41-
ticket2 = ArrowFlight::Ticket.new("data2")
43+
data1 = GLib::Bytes.new("data1")
44+
data2 = GLib::Bytes.new("data2")
45+
ticket1 = ArrowFlight::Ticket.new(data1)
46+
ticket2 = ArrowFlight::Ticket.new(data2)
4247
assert do
4348
not (ticket1 == ticket2)
4449
end

ci/scripts/c_glib_test.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ fi
3636

3737
pushd "${source_dir}"
3838

39-
ruby test/run-test.rb
39+
run_test_args=()
40+
if [ -n "${RUNNER_DEBUG}" ]; then
41+
run_test_args+=(-v)
42+
fi
43+
ruby test/run-test.rb "${run_test_args[@]}"
4044

4145
if [[ "$(uname -s)" == "Linux" ]]; then
4246
# TODO(kszucs): on osx it fails to load 'lgi.corelgilua51' despite that lgi

ruby/red-arrow-cuda/Rakefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ task :test do
3434
cd("dependency-check") do
3535
ruby("-S", "rake")
3636
end
37-
ruby("test/run-test.rb")
37+
args = []
38+
args << "-v" if ENV["RUNNER_DEBUG"]
39+
ruby("test/run-test.rb", *args)
3840
end
3941
end
4042

ruby/red-arrow-dataset/Rakefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ task :test do
3434
cd("dependency-check") do
3535
ruby("-S", "rake")
3636
end
37-
ruby("test/run-test.rb")
37+
args = []
38+
args << "-v" if ENV["RUNNER_DEBUG"]
39+
ruby("test/run-test.rb", *args)
3840
end
3941
end
4042

ruby/red-arrow-flight-sql/Rakefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ task :test do
3434
cd("dependency-check") do
3535
ruby("-S", "rake")
3636
end
37-
ruby("test/run-test.rb")
37+
args = []
38+
args << "-v" if ENV["RUNNER_DEBUG"]
39+
ruby("test/run-test.rb", *args)
3840
end
3941
end
4042

ruby/red-arrow-flight-sql/test/test-client.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class TestClient < Test::Unit::TestCase
1919
def setup
2020
@server = nil
2121
omit("Unstable on Windows") if Gem.win_platform?
22-
omit("Unstable on x86_64 macOS") if /x86_64-darwin/.match?(RUBY_PLATFORM)
22+
omit("Unstable on macOS") if /darwin/.match?(RUBY_PLATFORM)
2323
@server = Helper::Server.new
2424
@server.listen("grpc://127.0.0.1:0")
2525
@location = "grpc://127.0.0.1:#{@server.port}"

0 commit comments

Comments
 (0)