Skip to content

Commit

Permalink
fix(SwingSet): let vatManager creator override syscall comparison
Browse files Browse the repository at this point in the history
In normal operation, any syscall divergence during replay is a fatal
"anachrophobia error". But when we're replaying a vat for local debugging
purposes, we might want to be more tolerant, e.g. Errors being serialized
differently when the worker is in a debug mode.

This add a `managerOptions.compareSyscalls` which can override the way
transcript replay works.

We export `requireIdentical()` so callers can use it to build their custom
`compareSyscalls()` function.
  • Loading branch information
warner committed May 18, 2021
1 parent e45f5ad commit 94f3740
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 15 deletions.
1 change: 1 addition & 0 deletions packages/SwingSet/src/kernel/vatManager/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export function makeVatManagerFactory({
'vatParameters',
'vatConsole',
'name',
'compareSyscalls',
]);
const { setup, bundle, enableSetup = false } = managerOptions;
assert(setup || bundle);
Expand Down
7 changes: 6 additions & 1 deletion packages/SwingSet/src/kernel/vatManager/manager-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,15 @@ function makeManagerKit(
kernelKeeper,
vatSyscallHandler,
workerCanBlock,
compareSyscalls,
) {
assert(kernelSlog);
const vatKeeper = kernelKeeper.getVatKeeper(vatID);
const transcriptManager = makeTranscriptManager(vatKeeper, vatID);
const transcriptManager = makeTranscriptManager(
vatKeeper,
vatID,
compareSyscalls,
);

/** @type { (delivery: VatDeliveryObject) => Promise<VatDeliveryResult> } */
let deliverToWorker;
Expand Down
20 changes: 16 additions & 4 deletions packages/SwingSet/src/kernel/vatManager/manager-local.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ export function makeLocalVatManagerFactory(tools) {
};
// testLog is also a vatPower, only for unit tests

function prepare(vatID, vatSyscallHandler, meterRecord) {
function prepare(vatID, vatSyscallHandler, meterRecord, compareSyscalls) {
const mtools = harden({ stopGlobalMeter, meterRecord, refillAllMeters });
const mk = makeManagerKit(
vatID,
kernelSlog,
kernelKeeper,
vatSyscallHandler,
true,
compareSyscalls,
);

function finish(dispatch) {
Expand All @@ -60,8 +61,13 @@ export function makeLocalVatManagerFactory(tools) {
assert(!managerOptions.metered, X`unsupported`);
assert(setup instanceof Function, 'setup is not an in-realm function');

const { syscall, finish } = prepare(vatID, vatSyscallHandler, null);
const { vatParameters } = managerOptions;
const { vatParameters, compareSyscalls } = managerOptions;
const { syscall, finish } = prepare(
vatID,
vatSyscallHandler,
null,
compareSyscalls,
);
const { testLog } = allVatPowers;
const helpers = harden({}); // DEPRECATED, todo remove from setup()
const state = null; // TODO remove from setup()
Expand All @@ -85,6 +91,7 @@ export function makeLocalVatManagerFactory(tools) {
vatConsole,
liveSlotsConsole,
virtualObjectCacheSize,
compareSyscalls,
} = managerOptions;
assert(vatConsole, 'vats need managerOptions.vatConsole');

Expand All @@ -101,7 +108,12 @@ export function makeLocalVatManagerFactory(tools) {
});
}

const { syscall, finish } = prepare(vatID, vatSyscallHandler, meterRecord);
const { syscall, finish } = prepare(
vatID,
vatSyscallHandler,
meterRecord,
compareSyscalls,
);

const vatPowers = harden({
...baseVP,
Expand Down
2 changes: 2 additions & 0 deletions packages/SwingSet/src/kernel/vatManager/manager-nodeworker.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function makeNodeWorkerVatManagerFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
compareSyscalls,
} = managerOptions;
assert(!managerOptions.metered, 'not supported yet');
assert(!managerOptions.enableSetup, 'not supported at all');
Expand All @@ -53,6 +54,7 @@ export function makeNodeWorkerVatManagerFactory(tools) {
kernelKeeper,
vatSyscallHandler,
false,
compareSyscalls,
);

// start the worker and establish a connection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function makeNodeSubprocessFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
compareSyscalls,
} = managerOptions;
assert(!managerOptions.metered, 'not supported yet');
assert(!managerOptions.enableSetup, 'not supported at all');
Expand All @@ -30,6 +31,7 @@ export function makeNodeSubprocessFactory(tools) {
kernelKeeper,
vatSyscallHandler,
false,
compareSyscalls,
);

// start the worker and establish a connection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export function makeXsSubprocessFactory({
enableDisavow,
name,
metered,
compareSyscalls,
} = managerOptions;
assert(
!managerOptions.enableSetup,
Expand All @@ -65,6 +66,7 @@ export function makeXsSubprocessFactory({
kernelKeeper,
vatSyscallHandler,
true,
compareSyscalls,
);

/** @type { (item: Tagged) => unknown } */
Expand Down
29 changes: 19 additions & 10 deletions packages/SwingSet/src/kernel/vatManager/transcript.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import djson from '../djson';

export function makeTranscriptManager(vatKeeper, vatID) {
export function requireIdentical(vatID, originalSyscall, newSyscall) {
if (djson.stringify(originalSyscall) !== djson.stringify(newSyscall)) {
console.log(`anachrophobia strikes vat ${vatID}`);
console.log(`expected:`, djson.stringify(originalSyscall));
console.log(`got :`, djson.stringify(newSyscall));
return new Error(`historical inaccuracy in replay of ${vatID}`);
}
return undefined;
}

export function makeTranscriptManager(
vatKeeper,
vatID,
compareSyscalls = requireIdentical,
) {
let weAreInReplay = false;
let playbackSyscalls;
let currentEntry;
Expand Down Expand Up @@ -44,16 +58,11 @@ export function makeTranscriptManager(vatKeeper, vatID) {

let replayError;

function simulateSyscall(scObj) {
function simulateSyscall(newSyscall) {
const s = playbackSyscalls.shift();

if (djson.stringify(s.d) !== djson.stringify(scObj)) {
console.log(`anachrophobia strikes vat ${vatID}`);
console.log(`expected:`, djson.stringify(s.d));
console.log(`got :`, djson.stringify(scObj));
if (!replayError) {
replayError = new Error(`historical inaccuracy in replay of ${vatID}`);
}
const newReplayError = compareSyscalls(vatID, s.d, newSyscall);
if (newReplayError) {
replayError = newReplayError;
throw replayError;
}
return s.response;
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* vatParameters: Record<string, unknown>,
* virtualObjectCacheSize: number,
* name: string,
* compareSyscalls?: (originalSyscall: {}, newSyscall: {}) => Error | undefined,
* } & (HasBundle | HasSetup)} ManagerOptions
*/

Expand Down

0 comments on commit 94f3740

Please sign in to comment.