-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(swingset): do not record GC syscalls in the transcript
Consensus mode will depend upon GC being deterministic, but solo mode does not. Solo mode requires GC be "sufficiently deterministic", which means a finalizer may or may not run in any given crank. To support this, we must not record the GC-related syscalls (dropImport, retireImport, retireExport) in the transcript. When replaying a transcript, we ignore these syscalls as well. closes #3146 refs #2615 refs #2660 refs #2724
- Loading branch information
Showing
2 changed files
with
95 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// eslint-disable-next-line import/order | ||
import { test } from '../tools/prepare-test-env-ava'; | ||
|
||
import { makeDummySlogger } from '../src/kernel/slogger'; | ||
import { makeManagerKit } from '../src/kernel/vatManager/manager-helper'; | ||
|
||
const m1 = ['message', { method: 'foo', args: { body: '', slots: [] } }]; | ||
|
||
function setup(storedTranscript = []) { | ||
const vatID = 'vatID'; | ||
const slog = makeDummySlogger({}, () => console); | ||
const transcript = []; | ||
const vatKeeper = { | ||
addToTranscript(entry) { | ||
transcript.push(entry); | ||
}, | ||
vatStats() { | ||
return { transcriptCount: storedTranscript.length }; | ||
}, | ||
getTranscript() { | ||
return storedTranscript; | ||
}, | ||
}; | ||
const kernelKeeper = { | ||
getVatKeeper() { | ||
return vatKeeper; | ||
}, | ||
}; | ||
function vatSyscallHandler(_vso) { | ||
return ['ok', null]; | ||
} | ||
const workerCanBlock = false; | ||
const mk = makeManagerKit( | ||
vatID, | ||
slog, | ||
kernelKeeper, | ||
vatSyscallHandler, | ||
workerCanBlock, | ||
); | ||
const { syscallFromWorker } = mk; | ||
function deliver(_delivery) { | ||
// a syscall.subscribe is included in the transcript | ||
syscallFromWorker(['subscribe', 'p-1']); | ||
// but GC syscalls are not | ||
syscallFromWorker(['dropImports', ['o-1']]); | ||
syscallFromWorker(['retireImports', ['o-1']]); | ||
syscallFromWorker(['retireExports', ['o+2']]); | ||
syscallFromWorker(['subscribe', 'p-2']); | ||
return Promise.resolve(['ok', null, { usage: 0 }]); | ||
} | ||
mk.setDeliverToWorker(deliver); | ||
function shutdown() {} | ||
const manager = mk.getManager(shutdown); | ||
return { manager, transcript }; | ||
} | ||
|
||
test('gc syscalls are not included in transcript', async t => { | ||
const { manager, transcript } = setup(); | ||
await manager.deliver(m1); | ||
|
||
t.is(transcript.length, 1); | ||
t.deepEqual(transcript[0], { | ||
d: m1, | ||
syscalls: [ | ||
{ d: ['subscribe', 'p-1'], response: null }, | ||
{ d: ['subscribe', 'p-2'], response: null }, | ||
], | ||
}); | ||
}); | ||
|
||
test('gc syscalls are ignored during replay', async t => { | ||
const storedTranscript = [ | ||
{ | ||
d: m1, | ||
syscalls: [ | ||
{ d: ['subscribe', 'p-1'], response: null }, | ||
{ d: ['subscribe', 'p-2'], response: null }, | ||
], | ||
}, | ||
]; | ||
const { manager } = setup(storedTranscript); | ||
await manager.replayTranscript(); | ||
// success is that replayTranscript didn't throw anachrophobia error | ||
t.pass(); | ||
}); |