Skip to content

Commit

Permalink
Explicitly retain timer source when scheduling tasks (#138)
Browse files Browse the repository at this point in the history
Motivation:

When a task is scheduled using a `DispatchTimerSource` on a `NIOTSEventLoop`
the source is retain via a callback on the promise associated with the
scheduled task. This stops the source from deinit'd before the task is
run. However, the callback being added is an implementation details of
`Scheduled` and the retain cycle is incidental.

If that detail chnaged (such as in
apple/swift-nio#2011) then tasks may not run and
the promise could be leaked.

Modifications:

- Explicitly add a retain cycle between the future and the timer source
  which is broken by the promise being completed and callbacks run.

Result:

The timer source is kept alive until the event fires.
  • Loading branch information
glbrntt authored Jan 12, 2022
1 parent e7f5278 commit 8ab824b
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Sources/NIOTransportServices/NIOTSEventLoop.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ internal class NIOTSEventLoop: QoSEventLoop {
}
timerSource.resume()

// Create a retain cycle between the future and the timer source. This will be broken when the promise is
// completed by the event handler and this callback is run.
p.futureResult.whenComplete { _ in
timerSource.cancel()
}

return Scheduled(promise: p, cancellationTask: {
timerSource.cancel()
})
Expand Down

0 comments on commit 8ab824b

Please sign in to comment.