Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rewrite scanForDeadObjects to avoid retire-without-drop #9942

Merged
merged 4 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/SwingSet/test/gc/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,10 @@ export function buildRootObject() {
async makeInvitation0() {
await E(target).makeInvitationTarget(zoe);
},

// for #9939
async storePresenceInWeakSet() {
await E(target).store(A);
},
});
}
81 changes: 81 additions & 0 deletions packages/SwingSet/test/gc/gc-vat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,84 @@ test('forward to fake zoe', async t => {
// 'makeInvitationTarget' result promise with it, then dropped it
t.is(findClist(c, targetID, invitation), undefined);
});

// see #9939
test('drop without retire', async t => {
let targetID;
let didBOYD = false;
// const msgs = ['deliver', 'deliver-result', 'syscall', 'syscall-result'];

function slogSender(slogObj) {
const {
time: _1,
replay: _2,
crankNum: _3,
deliveryNum: _4,
monotime: _5,
...o
} = slogObj;
if (o.vatID !== targetID) return;
if (o.type === 'deliver' && o.kd[0] === 'bringOutYourDead') {
didBOYD = true;
}
// if (msgs.includes(o.type)) console.log(JSON.stringify(o));
}
const config = {
bootstrap: 'bootstrap', // v6
vats: {
bootstrap: {
// v6
sourceSpec: new URL('bootstrap.js', import.meta.url).pathname,
},
target: {
// v1
sourceSpec: new URL('vat-target.js', import.meta.url).pathname,
// avoid V8's GC nondeterminism, only needed on the target vat
creationOptions: { managerType: 'xs-worker' },
},
},
};
const kernelStorage = initSwingStore().kernelStorage;
await initializeSwingset(config, [], kernelStorage);
const c = await makeSwingsetController(kernelStorage, {}, { slogSender });
t.teardown(c.shutdown);

c.pinVatRoot('bootstrap');
targetID = c.vatNameToID('target');
c.pinVatRoot('target');

await c.run();

c.queueToVatRoot('bootstrap', 'storePresenceInWeakSet', []);
await c.run();

// now do enough dummy messages to trigger a new BOYD
didBOYD = false;
while (!didBOYD) {
c.queueToVatRoot('target', 'dummy', []);
await c.run();
}

// now tell vat-target to drop its WeakSet
c.queueToVatRoot('target', 'drop', []);
await c.run();

// and trigger a second BOYD
didBOYD = false;
while (!didBOYD) {
// this will fail once the vat is terminated
try {
c.queueToVatRoot('target', 'dummy', []);
} catch (e) {
if (/vat name "target" must exist/.test(e.message)) {
t.fail('vat terminated, bug is present');
break;
warner marked this conversation as resolved.
Show resolved Hide resolved
}
}
await c.run();
}
t.true(didBOYD);

// the test passes if the vat survived
return t.pass();
});
14 changes: 13 additions & 1 deletion packages/SwingSet/test/gc/vat-target.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Far, E } from '@endo/far';

export function buildRootObject() {
export function buildRootObject(_vatPowers, _vatParameters, baggage) {
/** @type { WeakSet | undefined } */
let ws = new WeakSet();

return Far('root', {
async two(A, B) {
// A=ko26 B=ko27
Expand All @@ -10,5 +13,14 @@ export function buildRootObject() {
makeInvitationTarget(zoe) {
return E(zoe).makeInvitationZoe();
},

// these three are for testing #9939
store: x => {
baggage.init('x', x);
assert(ws);
ws.add(x);
},
dummy: () => 0,
drop: () => (ws = undefined),
warner marked this conversation as resolved.
Show resolved Hide resolved
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,7 @@ test.serial('stakeAtom', async t => {
// restarting that one. For them to share bootstrap they'll each need a unique
// instance name, which will require paramatizing the the two builders scripts
// and the two core-eval functions.
//
// TODO(#9939): Flaky under Node.js until liveslots problem exposed by vows is fixed.
test.serial.skip('basicFlows', async t => {
test.serial('basicFlows', async t => {
const {
walletFactoryDriver,
buildProposal,
Expand Down
Loading
Loading