ReviewOS

craft-native/craft

fix(ios): ios_async's main-queue hop checks only that a slot is in use, not which lease

#225
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Two small gaps in packages/zig/src/ios_async.zig, found while adding the removal deadline for #211.

A queued hop checks only that the slot is in use

deliverJson, deliverErrorCode and deliverError compare the ticket's generation when they queue the main-queue hop. The hop itself, deliverOnMain, receives only the slot index and checks only in_use. completionFired, behind the pre-built BOOL blocks, likewise checks only in_use before queueing.

So if two deliver* calls for one ticket both pass their check before the first hop runs, the first hop answers and releases the slot. A new call can lease it, and the second hop then answers that call with the old outcome. A stale BOOL completion for a slot that has since been re-leased does the same.

Nothing in the tree does this today on purpose. #211's Siri deadline avoids it by deciding who answers under its own lock before calling deliver*. But the pool is supposed to be what makes a stale fire harmless, and here it is not.

Fix: carry the generation in the hop context, using the same encoding scheduleDeadline uses for its ticket, and compare it in deliverOnMain. Record the outcome only when the generation still matches in completionFired.

The header promises an error nothing sends

The comment on max_in_flight says a page that exceeds it "gets an explicit Busy error". Every caller returns NativeCallFailed when acquire returns null. Either add a Busy code and use it, or correct the comment.

Sign in to comment on this issue.