Skip to content

Comments

fix(ocap-kernel): enqueue async vat syscalls immediately when outside a crank#848

Merged
sirtimid merged 1 commit intomainfrom
sirtimid/fix-async-vat-syscall-buffering
Feb 24, 2026
Merged

fix(ocap-kernel): enqueue async vat syscalls immediately when outside a crank#848
sirtimid merged 1 commit intomainfrom
sirtimid/fix-async-vat-syscall-buffering

Conversation

@sirtimid
Copy link
Contributor

@sirtimid sirtimid commented Feb 23, 2026

Summary

  • When a vat's async operation (e.g. fetch) completes between cranks, the resulting syscall.resolve was buffered with immediate=false. Since no crank was active to flush the buffer, notifications were never delivered and the crank loop never restarted — causing the kernel to hang indefinitely.
  • Add isInCrank() to the kernel store's crank methods. In VatSyscall, check isInCrank() to determine the immediate flag: during a crank, buffer as before; outside a crank, enqueue immediately to wake the run queue.
  • This unblocks any vat method that chains multiple E() calls with real async I/O between vats (e.g. coordinator → provider(fetch) → coordinator → keyring → provider(fetch)).

Test plan

  • All 1983 ocap-kernel unit tests pass
  • All 62 kernel-test integration tests pass (persistence, liveslots, remotes, IO)
  • New unit tests for isInCrank() (true during crank, false outside)
  • New unit tests for out-of-crank syscall behavior (immediate=true)
  • Verified with eth-wallet's redeemDelegation pipeline (5-hop E() chain with real fetch I/O) — previously hung, now completes

🤖 Generated with Claude Code


Note

Medium Risk
Changes core syscall-to-queue behavior for send/resolve/notify, which can affect scheduling and ordering across the kernel run loop, though the change is small and covered by new tests.

Overview
Fixes a kernel hang by making vat syscalls that occur outside an active crank enqueue work immediately instead of buffering it for crank completion.

Adds isInCrank() to crank methods / kernel store, and updates VatSyscall (send, resolve, and resolved-subscribe notify) to set the queue immediate flag based on !kernelStore.isInCrank(), with new unit tests covering both the new API and out-of-crank behavior.

Written by Cursor Bugbot for commit 9a8f97c. This will update automatically on new commits. Configure here.

@sirtimid sirtimid requested a review from a team as a code owner February 23, 2026 18:19
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

@sirtimid sirtimid force-pushed the sirtimid/fix-async-vat-syscall-buffering branch from af60f5f to 830f243 Compare February 23, 2026 18:27
@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 76%
⬆️ +0.01%
6556 / 8626
🔵 Statements 75.89%
⬆️ +0.01%
6661 / 8777
🔵 Functions 73.8%
⬆️ +0.01%
1640 / 2222
🔵 Branches 75.37%
🟰 ±0%
2418 / 3208
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/ocap-kernel/src/store/methods/crank.ts 100%
🟰 ±0%
93.75%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/vats/VatSyscall.ts 100%
🟰 ±0%
95.45%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
Generated in workflow #3799 for commit 9a8f97c by the Vitest Coverage Report Action

@sirtimid sirtimid enabled auto-merge February 23, 2026 18:38
… a crank

When a vat's async operation (e.g. fetch) completes between cranks, the
resulting syscall.resolve was buffered with immediate=false. Since no
crank was active to flush the buffer, notifications were never delivered
and the crank loop never restarted — causing the kernel to hang
indefinitely.

Fix: add isInCrank() to the kernel store's crank methods. In
VatSyscall, check isInCrank() to determine the immediate flag:
- During a crank (immediate=false): buffer as before for atomic flush
- Outside a crank (immediate=true): enqueue directly to wake the run
  queue via the existing wakeUpTheRunQueue mechanism

This unblocks any vat method that chains multiple E() calls with real
async I/O between vats (e.g. coordinator → provider with fetch →
coordinator → keyring → provider).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sirtimid sirtimid force-pushed the sirtimid/fix-async-vat-syscall-buffering branch from b0f2e24 to 9a8f97c Compare February 24, 2026 19:11
Copy link
Contributor

@FUDCo FUDCo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I think this is right.

@sirtimid sirtimid added this pull request to the merge queue Feb 24, 2026
Merged via the queue into main with commit c37577b Feb 24, 2026
29 checks passed
@sirtimid sirtimid deleted the sirtimid/fix-async-vat-syscall-buffering branch February 24, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants