Repository navigation
v0.12.0 — Non-Blocking I/O & Concurrency Fixes
Non-Blocking I/O Modernization
Traceroute I/O: poll(2) replaced with DispatchSourceRead
TraceReceiveOperationandStreamingTraceReceiveOperationnow use kqueue-backedDispatchSourceReadfor ICMP socket readiness, replacing the legacypoll(2)busy loopDispatchSourceTimerreplaces manual deadline arithmetic for both the overall timeout and the streaming retry timer- Eliminates thread-blocking: the cooperative thread pool is never stalled waiting for socket data
- Completes the I/O modernization started in v0.11.2 (TCP/UDP probes) and v0.8.0 (ping), bringing all socket-based operations to event-driven I/O
Concurrency Bug Fixes
Data race elimination in trace operations
TraceReceiveOperation.cancel()now sets the finished flag under lock and dispatches source cleanup to the serial queue, preventing races between cancellation (any thread) andhandleRead()/setupSources()(serial queue)- Same fix applied to
StreamingTraceReceiveOperation.cancel() finish()in both operations simplified to only run on the serial queue —hops,reachedTTL, andreceivedTTLsno longer need lock-protected copies since they're only mutated on that same queuesetupSources()now guards against setup aftercancel()has already completed, preventing leaked DispatchSources that would hold strong references to the operation
HTTPProbe delegate thread safety
NoRedirectDelegateandMetricsDelegatenow protecttaskMetricswithNSLock, eliminating a theoretical data race between URLSession's internal queue and the caller'sextractTimingMetrics()read
Config Validation
SwiftFTRConfig.init(): precondition thatmaxHopsis 1...255,maxWaitMsis positive,payloadSizeis non-negativeStreamingTraceConfig.init(): precondition thatmaxHopsis 1...255,probeTimeoutis positive- Prevents runtime crashes from
1...0range construction whenmaxHops == 0
Compatibility
- No breaking changes to public APIs
- All 157 tests passing
- Requires macOS 13+, Swift 6.1+
What's Changed
Full Changelog: v0.11.5...v0.12.0