You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Raising this as unconfirmed — I believe it is a bug, but I have not verified it against a running remote link, and there is a plausible reading in which it is by design. Evidence and the counter-case both below so it can be judged independently.
Observed
With a real kernel store: an object exported by v1, imported by both a vat (v2) and a remote (r1), dropped by both, then orphaned by its owner. After collectGarbage():
The vat importer gets a retireImport. The remote importer gets nothing, and the audit reports its c-list entry as a dangling reference — on that crank and on every crank after.
Mechanism
retireKernelObjects (store/methods/gc.ts:138-149) builds its actions from getImporters(koid). getImporters filters getVatIDs() (store/methods/vat.ts:150-157), which is derived from the vatConfig. key prefix — so it enumerates vats only, never remotes. deleteKernelObject is called in the same loop.
The remote's import c-list entry therefore outlives the object it names, with no action scheduled to tear it down. Since #1010 that entry also holds a recognizable count (store/methods/clist.ts:50), which is why the audit now has something to disagree about.
Why I think it matters
Two consequences at different confidence levels:
High confidence: the c-list entry and its counts leak. Nothing will ever remove them.
Medium confidence: any future test that retires an object a remote still recognises will fail auditRefCounts, and kernel-test enables auditing on every kernel it builds (packages/kernel-test/src/utils.ts:98).
Why this might not be an issue
It is latent today. Reproducing it took an explicit initEndpoint('r1') and a hand-driven drop/orphan sequence. Nothing in kernel-test drives that, which is why CI is green — fix(ocap-kernel): make c-list import accounting symmetric #1010's claim that auditRefCounts is clean across kernel-test is correct; the topology simply isn't covered.
I have not verified whether remotes are meant to learn about retirement through a different channel — incarnation-change reconciliation, for instance. If they are, then getImporters is right as it stands and the correct fix is to widen the audit's exemption at refcount-audit.ts:116-124 instead. Someone who knows the remote GC protocol should decide which way this goes; the two fixes are not interchangeable.
Reproduction
A failing test exists locally, not yet pushed:
yarn vitest run --config packages/ocap-kernel/vitest.config.ts \
packages/ocap-kernel/src/store/methods/refcount-audit.test.ts \
-t "retires a remote importer" --coverage=false
It asserts that both importers receive a retireImport and that the audit is clean afterwards. Happy to push it, though which assertion is correct depends on the open question above, so I'd rather settle that first.
Raising this as unconfirmed — I believe it is a bug, but I have not verified it against a running remote link, and there is a plausible reading in which it is by design. Evidence and the counter-case both below so it can be judged independently.
Observed
With a real kernel store: an object exported by
v1, imported by both a vat (v2) and a remote (r1), dropped by both, then orphaned by its owner. AftercollectGarbage():The vat importer gets a
retireImport. The remote importer gets nothing, and the audit reports its c-list entry as a dangling reference — on that crank and on every crank after.Mechanism
retireKernelObjects(store/methods/gc.ts:138-149) builds its actions fromgetImporters(koid).getImportersfiltersgetVatIDs()(store/methods/vat.ts:150-157), which is derived from thevatConfig.key prefix — so it enumerates vats only, never remotes.deleteKernelObjectis called in the same loop.The remote's import c-list entry therefore outlives the object it names, with no action scheduled to tear it down. Since #1010 that entry also holds a recognizable count (
store/methods/clist.ts:50), which is why the audit now has something to disagree about.Why I think it matters
Two consequences at different confidence levels:
auditRefCounts, andkernel-testenables auditing on every kernel it builds (packages/kernel-test/src/utils.ts:98).Why this might not be an issue
initEndpoint('r1')and a hand-driven drop/orphan sequence. Nothing inkernel-testdrives that, which is why CI is green — fix(ocap-kernel): make c-list import accounting symmetric #1010's claim thatauditRefCountsis clean acrosskernel-testis correct; the topology simply isn't covered.retireImportbefore fix(ocap-kernel): make c-list import accounting symmetric #1010 either. What changed is that the entry now carries a count, and there is now a checker that notices.getImportersis right as it stands and the correct fix is to widen the audit's exemption atrefcount-audit.ts:116-124instead. Someone who knows the remote GC protocol should decide which way this goes; the two fixes are not interchangeable.Reproduction
A failing test exists locally, not yet pushed:
It asserts that both importers receive a
retireImportand that the audit is clean afterwards. Happy to push it, though which assertion is correct depends on the open question above, so I'd rather settle that first.Found while reviewing #1010.