Skip to content

Commit f278afd

Browse files
authored
Make Socket hold a reference to its Context (#229)
This prevents the `Context` from being garbage collected while the `Socket` is still alive, otherwise the `Socket` would be closed by the `Context`'s finalizer while the `Socket` is potentially still in use.
1 parent d2edc88 commit f278afd

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

src/socket.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ A ZMQ socket.
33
"""
44
mutable struct Socket
55
data::Ptr{Cvoid}
6+
context::Context
67
pollfd::FDWatcher
78

89
@doc """
@@ -15,7 +16,7 @@ mutable struct Socket
1516
if p == C_NULL
1617
throw(StateError(jl_zmq_error_str()))
1718
end
18-
socket = new(p)
19+
socket = new(p, ctx)
1920
setfield!(socket, :pollfd, FDWatcher(fd(socket), #=readable=#true, #=writable=#false))
2021
finalizer(close, socket)
2122
push!(getfield(ctx, :sockets), WeakRef(socket))

test/runtests.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,23 @@ using ZMQ, Test
1414
@test_throws StateError Socket(ctx, PUB)
1515
end
1616

17+
# This test is in its own function to keep it simple and try to trick Julia into
18+
# thinking it can safely GC the Context.
19+
function context_gc_test()
20+
ctx = Context()
21+
s = Socket(ctx, PUB)
22+
23+
# Force garbage collection to attempt to delete ctx
24+
GC.gc()
25+
26+
# But it shouldn't be garbage collected since the socket should have a
27+
# reference to it, so the socket should still be open.
28+
@test isopen(s)
29+
end
30+
1731
@testset "ZMQ sockets" begin
32+
context_gc_test()
33+
1834
s=Socket(PUB)
1935
@test s isa Socket
2036
ZMQ.close(s)

0 commit comments

Comments
 (0)