Skip to content

Commit 0e48aac

Browse files
alexbatalovRX14
authored andcommittedJan 2, 2018
Fix missing GC.add_finalizer throughout the stdlib (#5367)
1 parent b549408 commit 0e48aac

File tree

9 files changed

+107
-0
lines changed

9 files changed

+107
-0
lines changed
 

‎spec/std/object_spec.cr

+18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require "spec"
2+
require "../support/finalize"
23

34
private class StringWrapper
45
delegate downcase, to: @string
@@ -97,6 +98,18 @@ private class TestObject
9798
end
9899
end
99100

101+
private class TestObjectWithFinalize
102+
property key : Symbol?
103+
104+
def finalize
105+
if key = self.key
106+
State.inc(key)
107+
end
108+
end
109+
110+
def_clone
111+
end
112+
100113
describe Object do
101114
describe "delegate" do
102115
it "delegates" do
@@ -337,4 +350,9 @@ describe Object do
337350
it "#unsafe_as" do
338351
0x12345678.unsafe_as(Tuple(UInt8, UInt8, UInt8, UInt8)).should eq({0x78, 0x56, 0x34, 0x12})
339352
end
353+
354+
it "calls #finalize on #clone'd objects" do
355+
obj = TestObjectWithFinalize.new
356+
assert_finalizes(:clone) { obj.clone }
357+
end
340358
end

‎spec/std/openssl/ssl/context_spec.cr

+21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
require "spec"
22
require "openssl"
3+
require "../../../support/finalize"
4+
5+
class OpenSSL::SSL::Context
6+
property key : Symbol?
7+
8+
def finalize
9+
if key = self.key
10+
State.inc(key)
11+
end
12+
13+
previous_def
14+
end
15+
end
316

417
describe OpenSSL::SSL::Context do
518
it "new for client" do
@@ -147,4 +160,12 @@ describe OpenSSL::SSL::Context do
147160
context.alpn_protocol = "h2"
148161
end
149162
{% end %}
163+
164+
it "calls #finalize on insecure client context" do
165+
assert_finalizes(:insecure_client_ctx) { OpenSSL::SSL::Context::Client.insecure }
166+
end
167+
168+
it "calls #finalize on insecure server context" do
169+
assert_finalizes(:insecure_server_ctx) { OpenSSL::SSL::Context::Server.insecure }
170+
end
150171
end

‎spec/std/reference_spec.cr

+16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require "spec"
2+
require "../support/finalize"
23

34
private module ReferenceSpec
45
class TestClass
@@ -35,6 +36,16 @@ private module ReferenceSpec
3536
def initialize(@x : Int32)
3637
end
3738
end
39+
40+
class TestClassWithFinalize
41+
property key : Symbol?
42+
43+
def finalize
44+
if key = self.key
45+
State.inc(key)
46+
end
47+
end
48+
end
3849
end
3950

4051
describe "Reference" do
@@ -110,4 +121,9 @@ describe "Reference" do
110121
ReferenceSpec::TestClassBase.new.pretty_inspect.should match(/\A#<ReferenceSpec::TestClassBase:0x[0-9a-f]+>\Z/)
111122
ReferenceSpec::TestClass.new(42, "foo").pretty_inspect.should match(/\A#<ReferenceSpec::TestClass:0x[0-9a-f]+ @x=42, @y="foo">\Z/)
112123
end
124+
125+
it "calls #finalize on #dup'ed objects" do
126+
obj = ReferenceSpec::TestClassWithFinalize.new
127+
assert_finalizes(:clone) { obj.dup }
128+
end
113129
end

‎spec/std/yaml/mapping_spec.cr

+19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require "spec"
22
require "yaml"
3+
require "../../support/finalize"
34

45
private class YAMLPerson
56
YAML.mapping({
@@ -124,6 +125,20 @@ class YAMLRecursiveHash
124125
})
125126
end
126127

128+
private class YAMLWithFinalize
129+
YAML.mapping({
130+
value: YAML::Any,
131+
})
132+
133+
property key : Symbol?
134+
135+
def finalize
136+
if key = self.key
137+
State.inc(key)
138+
end
139+
end
140+
end
141+
127142
describe "YAML mapping" do
128143
it "parses person" do
129144
person = YAMLPerson.from_yaml("---\nname: John\nage: 30\n")
@@ -445,4 +460,8 @@ describe "YAML mapping" do
445460
yaml.last_name_present?.should be_false
446461
end
447462
end
463+
464+
it "calls #finalize" do
465+
assert_finalizes(:yaml) { YAMLWithFinalize.from_yaml("---\nvalue: 1\n") }
466+
end
448467
end

‎spec/support/finalize.cr

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class State
2+
@@count = {} of Symbol => Int64
3+
4+
def self.inc(key)
5+
@@count[key] = @@count.fetch(key, 0i64) + 1
6+
end
7+
8+
def self.count(key)
9+
@@count.fetch(key, 0i64)
10+
end
11+
12+
def self.reset
13+
@@count.clear
14+
end
15+
end
16+
17+
def assert_finalizes(key)
18+
State.reset
19+
State.count(key).should eq(0)
20+
21+
10.times do
22+
obj = yield
23+
obj.key = key
24+
end
25+
26+
GC.collect
27+
28+
State.count(key).should be > 0
29+
end

‎src/object.cr

+1
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,7 @@ class Object
11821182
def clone
11831183
clone = \{{@type}}.allocate
11841184
clone.initialize_copy(self)
1185+
GC.add_finalizer(clone) if clone.responds_to?(:finalize)
11851186
clone
11861187
end
11871188

‎src/openssl/ssl/context.cr

+1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ abstract class OpenSSL::SSL::Context
178178
protected def self.insecure(method : LibSSL::SSLMethod)
179179
obj = allocate
180180
obj._initialize_insecure(method)
181+
GC.add_finalizer(obj)
181182
obj
182183
end
183184

‎src/reference.cr

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Reference
4646
{% else %}
4747
dup = self.class.allocate
4848
dup.as(Void*).copy_from(self.as(Void*), instance_sizeof(self))
49+
GC.add_finalizer(dup) if dup.responds_to?(:finalize)
4950
dup
5051
{% end %}
5152
end

‎src/yaml/mapping.cr

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ module YAML
106106
ctx.record_anchor(node, instance)
107107

108108
instance.initialize(ctx, node, nil)
109+
GC.add_finalizer(instance) if instance.responds_to?(:finalize)
109110
instance
110111
end
111112

0 commit comments

Comments
 (0)