From d5a76ff64b2d6b5889679df1b21d9d1e9bcd1ae8 Mon Sep 17 00:00:00 2001 From: Fang-Pen Lin Date: Wed, 15 Aug 2018 15:40:06 -0700 Subject: [PATCH 1/2] Add test for reference cycle --- Tests/EmbassyTests/SelectorEventLoopTests.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/EmbassyTests/SelectorEventLoopTests.swift b/Tests/EmbassyTests/SelectorEventLoopTests.swift index 23cbd00..c57603f 100644 --- a/Tests/EmbassyTests/SelectorEventLoopTests.swift +++ b/Tests/EmbassyTests/SelectorEventLoopTests.swift @@ -218,4 +218,12 @@ class SelectorEventLoopTests: XCTestCase { } XCTAssertEqual(readData, ["hello", "baby"]) } + + func testEventLoopReferenceCycle() { + // Notice: we had a reference cycle from the setReader callback to the + // selector loop object before, we ensure that when loop is not hold + // by anybody, it should be released here + weak var loop = try! SelectorEventLoop(selector: try! TestingSelector()) + XCTAssertNil(loop) + } } From 7673fefb5880dcbac5d6ac22c3f001cf8897dfd5 Mon Sep 17 00:00:00 2001 From: Fang-Pen Lin Date: Wed, 15 Aug 2018 15:44:44 -0700 Subject: [PATCH 2/2] Fix the broken test --- Sources/SelectorEventLoop.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/SelectorEventLoop.swift b/Sources/SelectorEventLoop.swift index bb7ddbb..2d001f2 100644 --- a/Sources/SelectorEventLoop.swift +++ b/Sources/SelectorEventLoop.swift @@ -48,6 +48,10 @@ public final class SelectorEventLoop: EventLoop { IOUtils.setBlocking(fileDescriptor: pipeReceiver, blocking: false) // subscribe to pipe receiver read-ready event, do nothing, just allow selector // to be interrupted + + // Notice: we use a local copy of pipeReceiver to avoid referencing self + // here, thus we won't have reference cycle problem + let localPipeReceiver = pipeReceiver setReader(pipeReceiver) { // consume the pipe receiver, so that it won't keep triggering read event let size = PIPE_BUF @@ -55,7 +59,7 @@ public final class SelectorEventLoop: EventLoop { var readSize = 1 while readSize > 0 { readSize = bytes.withUnsafeMutableBytes { pointer in - return SystemLibrary.read(self.pipeReceiver, pointer, Int(size)) + return SystemLibrary.read(localPipeReceiver, pointer, Int(size)) } } }