Repository navigation
Conversation
…line `EndpointFlow.scheduleWriteFlush` retried `requestFlush()` whenever `withFlow` returned `nil`, assuming `context.async` always defers the task until the current flow call has returned. A scheduler that runs `runImmediate` tasks on the caller's stack runs the flush task inside the `send` that still holds the flow, so `withFlow` returned `nil` and the retry recursed until the stack overflowed. Changed: * Handed the flush to the call holding the flow through `EndpointFlowParent.deferWriteFlush()` instead of retrying from the flush task. * Tracked the pending flush in `NetworkChannelBase` with `FlowBorrow.borrowed(flushPending:)`, and flushed in `releaseFlow()` before ending the borrow. * Made `EndpointFlow.flushWrites()` internal so the owner can call it. * Added `SwiftNetworkEndpointFlowInlineSchedulerTests`, which runs the flush task inline during a `send`. Result: * Sending on a ready flow no longer recurses when the scheduler runs tasks inline. * The new test fails without the change and passes with it.
|
/benchmark |
Benchmark results
🟢 lower, 🔴 higher, ➖ no change: a change must exceed 0.25% and 3 times the variation between repeats of either build. QUICTransfer
Allocations: base 424451, 424344, 424435; head 424312, 424474, 424277 QUICStreamLoad
Allocations: base 364771, 364205, 364783; head 364595, 364775, 364951 IPUDPTransfer
Allocations: base 904251, 904256, 904256; head 904246, 904246, 904251 |
…line
EndpointFlow.scheduleWriteFlushretriedrequestFlush()wheneverwithFlowreturnednil, assumingcontext.asyncalways defers the task until the current flow call has returned. A scheduler that runsrunImmediatetasks on the caller's stack runs the flush task inside thesendthat still holds the flow, sowithFlowreturnedniland the retry recursed until the stack overflowed.Changed:
EndpointFlowParent.deferWriteFlush()instead of retrying from the flush task.NetworkChannelBasewithFlowBorrow.borrowed(flushPending:), and flushed inreleaseFlow()before ending the borrow.EndpointFlow.flushWrites()internal so the owner can call it.SwiftNetworkEndpointFlowInlineSchedulerTests, which runs the flush task inline during asend.Result: