Cancel the event reader before closing the descriptor
`deinit` closed the inotify descriptor while its dispatch source was still active. The kernel drops the epoll registration on close, but libdispatch keeps its own; an instance created afterwards that reuses the descriptor number could inherit that stale state and never receive events. Roughly one test run in three lost a single event this way. The reader is now cancelled in `deinit` and the descriptor closed in its cancel handler, as libdispatch requires.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import Inotify
|
||||
|
||||
@Suite("Instance Lifecycle")
|
||||
struct LifecycleTests {
|
||||
@Test func aDeallocatedInstanceDoesNotStealEventsOfItsSuccessor() async throws {
|
||||
try await withTempDir { dir in
|
||||
let filename = "after-reuse.txt"
|
||||
do {
|
||||
let predecessor = try Inotify()
|
||||
try await predecessor.addWatch(path: dir, mask: .create)
|
||||
}
|
||||
|
||||
let events = try await getEventsForTrigger(
|
||||
in: dir,
|
||||
mask: .create,
|
||||
) { try createFile(at: "\($0)/\(filename)") }
|
||||
|
||||
let createEvent = events.first { $0.mask.contains(.create) && $0.path.lastComponent?.string == filename }
|
||||
#expect(createEvent != nil, "Expected CREATE for '\(filename)', got: \(events)")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user