Skip to content

Commit

Permalink
fix(swingset): add vatOptions.enableDisavow, dummy vatPowers.disavow
Browse files Browse the repository at this point in the history
The new `vatPowers.disavow` doesn't do anything yet, but is at least
exercised by test-liveslots.js

The `enableDisavow` option is only available for static vats. The `endow`
function cannot be enabled on dynamic vats.

refs #2636, but won't close it until #2635 is implemented and `disavow()`
routes into `syscall.dropImports()`
  • Loading branch information
warner committed Mar 19, 2021
1 parent e407fa2 commit 4f43a5c
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 12 deletions.
5 changes: 5 additions & 0 deletions packages/SwingSet/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,8 @@ not yet supported.
level `setup()` API, which allows a vat to be defined independent of
the liveslots framework (defaults to `false` if omitted). (If you
don't understand what this means, do not use this.)

- `enableDisavow`, if true, adds `vatPowers.disavow()`, which allows vat code
to explicitly disavow interest in an imported Presence. This will trigger a
`syscall.dropImports` of the associated object ID. By default, this
function is not added to `vatPowers`.
9 changes: 9 additions & 0 deletions packages/SwingSet/docs/static-vats.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Static vats currently receive the following objects in their `buildRootObject()`
* `transformTildot`
* `exitVat`
* `exitVatWithFailure`
* `disavow`, but only if `creationOptions.enableDisavow` was truthy

(dynamic vats do not get `makeGetMeter` or `transformMetering`)

Expand All @@ -89,6 +90,14 @@ This is particularly useful for vats that implement a REPL, so operators can inc

A vat may signal to the kernel that it should be terminated at the end of its current crank. Two powers are provided to do this: `exitVat(completion)` and `exitVatWithFailure(reason)`. These powers will work in any vat but are primarily useful in dynamic vats. The two differ in how the circumstances of termination are signalled to holders of the vat's `done` promise: `exitVat` fulfills that promise with the value provided in the `completion` parameter, whereas `exitVatWithFailure` rejects the promise with the value provided in the `reason` parameter. Conventionally, `completion` will be a string and `reason` will be an `Error`, but any serializable object may be used for either. After the crank in which either of these powers is invoked, no further messages will be delivered to the vat; instead, any such messages will be rejected with a `'vat terminated'` error. Any outstanding promises for which the vat was the decider will also be rejected in the same way. The vat and any resources it holds will become eligible for garbage collection. However, the crank itself will end normally, meaning that any actions taken by the vat during the crank in which either exit power was invoked will become part of the persisted state of the swingset, including messages that were sent from the vat during that crank (including, notably, actions taken _after_ the exit power was invoked but before the crank finished).

### explicitly dropping imported Presences: `disavow`

If enabled, vat code can explicitly drop an imported Presence by calling `vatPowers.disavow(presence)`, which will cause liveslots to invoke `syscall.dropImports()` on the Presence's object ID. This is primarily for testing the GC syscalls without relying upon engine-level finalizers (which are non-trivial to force), especially before the finalization code is complete.

Once disavowed, the Presence stops working. Any messages sent to it (with `E(disavowedPresence).method(args)`) or which reference it (`E(target).method(disavowedPresence)`) will be rejected with an error. Any promise resolutions that reference it will fail somewhat silently (just like unhandled rejected promises).

It's not clear that `disavow` is a good idea: it may be removed once the GC implementation is complete.

## Configuring Vats

Each swingset is created by a call to `buildVatController`, which takes a `config` argument. The `config.vats` property is a Map of named vat definitions: each value is an object with `sourcepath` and `options`. The `sourcepath` is the filename of the vat definition file (the one that exports `buildRootObject`).
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/src/kernel/initializeKernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export function initializeKernel(config, hostStorage, verbose = false) {
'enablePipelining',
'metered',
'managerType',
'enableDisavow',
'enableSetup',
'enableInternalMetering',
'virtualObjectCacheSize',
Expand Down
22 changes: 20 additions & 2 deletions packages/SwingSet/src/kernel/liveSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE = 3; // XXX ridiculously small value to
* @param {*} syscall Kernel syscall interface that the vat will have access to
* @param {*} forVatID Vat ID label, for use in debug diagostics
* @param {number} cacheSize Maximum number of entries in the virtual object state cache
* @param {boolean} enableDisavow
* @param {*} vatPowers
* @param {*} vatParameters
* @param {Console} console
Expand All @@ -35,12 +36,13 @@ const DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE = 3; // XXX ridiculously small value to
* create a root object for the new vat The caller provided buildRootObject
* function produces and returns the new vat's root object:
*
* buildRootObject(vatPowers, vatParameters)
* buildRootObject(vatPowers, vatParameters)
*/
function build(
syscall,
forVatID,
cacheSize,
enableDisavow,
vatPowers,
vatParameters,
console,
Expand Down Expand Up @@ -611,6 +613,8 @@ function build(
syscall.exit(true, m.serialize(harden(reason)));
}

function disavow(_presence) {}

// vats which use D are in: acorn-eventual-send, cosmic-swingset
// (bootstrap, bridge, vat-http), swingset

Expand All @@ -623,9 +627,20 @@ function build(
assert(!didRoot);
didRoot = true;

const disavowPowers = {};
if (enableDisavow) {
disavowPowers.disavow = disavow;
}

// here we finally invoke the vat code, and get back the root object
const rootObject = buildRootObject(
harden({ D, exitVat, exitVatWithFailure, ...vatPowers }),
harden({
D,
exitVat,
exitVatWithFailure,
...disavowPowers,
...vatPowers,
}),
harden(vatParameters),
);
assert.equal(passStyleOf(rootObject), REMOTE_STYLE);
Expand All @@ -648,6 +663,7 @@ function build(
* @param {*} vatPowers
* @param {*} vatParameters
* @param {number} cacheSize Upper bound on virtual object cache size
* @param {boolean} enableDisavow
* @param {*} _gcTools
* @param {Console} [liveSlotsConsole]
* @returns {*} { vatGlobals, dispatch, setBuildRootObject }
Expand Down Expand Up @@ -680,6 +696,7 @@ export function makeLiveSlots(
vatPowers = harden({}),
vatParameters = harden({}),
cacheSize = DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE,
enableDisavow = false,
_gcTools,
liveSlotsConsole = console,
) {
Expand All @@ -691,6 +708,7 @@ export function makeLiveSlots(
syscall,
forVatID,
cacheSize,
enableDisavow,
allVatPowers,
vatParameters,
liveSlotsConsole,
Expand Down
3 changes: 3 additions & 0 deletions packages/SwingSet/src/kernel/loadVat.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export function makeVatLoader(stuff) {
'name',
'vatParameters',
'managerType',
'enableDisavow',
'enableSetup',
'enablePipelining',
'virtualObjectCacheSize',
Expand Down Expand Up @@ -155,6 +156,7 @@ export function makeVatLoader(stuff) {
vatParameters = {},
managerType,
enableSetup = false,
enableDisavow = false,
enablePipelining = false,
virtualObjectCacheSize,
name,
Expand Down Expand Up @@ -205,6 +207,7 @@ export function makeVatLoader(stuff) {
managerType,
bundle: vatSourceBundle,
metered,
enableDisavow,
enableSetup,
enablePipelining,
enableInternalMetering: !isDynamic,
Expand Down
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 @@ -57,6 +57,7 @@ export function makeVatManagerFactory({
'setup',
'bundle',
'metered',
'enableDisavow',
'enableSetup',
'enableInternalMetering',
'liveSlotsConsole',
Expand Down
2 changes: 2 additions & 0 deletions packages/SwingSet/src/kernel/vatManager/manager-local.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export function makeLocalVatManagerFactory(tools) {
async function createFromBundle(vatID, bundle, managerOptions) {
const {
metered = false,
enableDisavow = false,
enableSetup = false,
enableInternalMetering = false,
vatParameters = {},
Expand All @@ -110,6 +111,7 @@ export function makeLocalVatManagerFactory(tools) {
vatPowers,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
gcTools,
liveSlotsConsole,
);
Expand Down
14 changes: 12 additions & 2 deletions packages/SwingSet/src/kernel/vatManager/manager-nodeworker.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ export function makeNodeWorkerVatManagerFactory(tools) {
const { makeNodeWorker, kernelKeeper, testLog, decref } = tools;

function createFromBundle(vatID, bundle, managerOptions) {
const { vatParameters, virtualObjectCacheSize } = managerOptions;
const {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
} = managerOptions;
assert(!managerOptions.metered, 'not supported yet');
assert(!managerOptions.enableSetup, 'not supported at all');
if (managerOptions.enableInternalMetering) {
Expand Down Expand Up @@ -123,7 +127,13 @@ export function makeNodeWorkerVatManagerFactory(tools) {
gotWorker(worker);

parentLog(`instructing worker to load bundle..`);
sendToWorker(['setBundle', bundle, vatParameters, virtualObjectCacheSize]);
sendToWorker([
'setBundle',
bundle,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
]);

function deliver(delivery) {
parentLog(`sending delivery`, delivery);
Expand Down
14 changes: 12 additions & 2 deletions packages/SwingSet/src/kernel/vatManager/manager-subprocess-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ export function makeNodeSubprocessFactory(tools) {
const { startSubprocessWorker, kernelKeeper, testLog, decref } = tools;

function createFromBundle(vatID, bundle, managerOptions) {
const { vatParameters, virtualObjectCacheSize } = managerOptions;
const {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
} = managerOptions;
assert(!managerOptions.metered, 'not supported yet');
assert(!managerOptions.enableSetup, 'not supported at all');
if (managerOptions.enableInternalMetering) {
Expand Down Expand Up @@ -123,7 +127,13 @@ export function makeNodeSubprocessFactory(tools) {
fromChild.on('data', handleUpstream);

parentLog(`instructing worker to load bundle..`);
sendToWorker(['setBundle', bundle, vatParameters, virtualObjectCacheSize]);
sendToWorker([
'setBundle',
bundle,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
]);

function deliver(delivery) {
parentLog(`sending delivery`, delivery);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ export function makeXsSubprocessFactory({
*/
async function createFromBundle(vatID, bundle, managerOptions) {
parentLog(vatID, 'createFromBundle', { vatID });
const { vatParameters, virtualObjectCacheSize } = managerOptions;
const {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
} = managerOptions;
assert(!managerOptions.metered, 'xs-worker: metered not supported yet');
assert(
!managerOptions.enableSetup,
Expand Down Expand Up @@ -150,6 +154,7 @@ export function makeXsSubprocessFactory({
bundle,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
]);
if (bundleReply[0] === 'dispatchReady') {
parentLog(vatID, `bundle loaded. dispatch ready.`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ parentPort.on('message', ([type, ...margs]) => {
workerLog(`got start`);
sendUplink(['gotStart']);
} else if (type === 'setBundle') {
const [bundle, vatParameters, virtualObjectCacheSize] = margs;
const [
bundle,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
] = margs;

function testLog(...args) {
sendUplink(['testLog', ...args]);
Expand Down Expand Up @@ -109,6 +114,7 @@ parentPort.on('message', ([type, ...margs]) => {
vatPowers,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
gcTools,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,12 @@ fromParent.on('data', ([type, ...margs]) => {
workerLog(`got start`);
sendUplink(['gotStart']);
} else if (type === 'setBundle') {
const [bundle, vatParameters, virtualObjectCacheSize] = margs;
const [
bundle,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
] = margs;

function testLog(...args) {
sendUplink(['testLog', ...args]);
Expand Down Expand Up @@ -129,6 +134,7 @@ fromParent.on('data', ([type, ...margs]) => {
vatPowers,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
gcTools,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,15 @@ function makeWorker(port) {
* @param {unknown} bundle
* @param {unknown} vatParameters
* @param {unknown} virtualObjectCacheSize
* @param {boolean} enableDisavow
* @returns { Promise<Tagged> }
*/
async function setBundle(
vatID,
bundle,
vatParameters,
virtualObjectCacheSize,
enableDisavow,
) {
/** @type { (item: Tagged) => unknown } */
function doSyscall(vatSyscallObject) {
Expand Down Expand Up @@ -237,6 +239,7 @@ function makeWorker(port) {
vatPowers,
vatParameters,
cacheSize,
enableDisavow,
gcTools,
);

Expand All @@ -260,9 +263,11 @@ function makeWorker(port) {
async function handleItem([tag, ...args]) {
workerLog('handleItem', tag, args.length);
switch (tag) {
case 'setBundle':
case 'setBundle': {
assert(!dispatch, 'cannot setBundle again');
return setBundle(args[0], args[1], args[2], args[3]);
const enableDisavow = !!args[4];
return setBundle(args[0], args[1], args[2], args[3], enableDisavow);
}
case 'deliver': {
assert(dispatch, 'cannot deliver before setBundle');
const [dtype, ...dargs] = args;
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 @@ -21,6 +21,7 @@
* managerType: 'local' | 'nodeWorker' | 'node-subprocess' | 'xs-worker',
* metered?: boolean,
* enableInternalMetering?: boolean,
* enableDisavow?: boolean,
* vatParameters: Record<string, unknown>,
* virtualObjectCacheSize: number,
* } & (HasBundle | HasSetup)} ManagerOptions
Expand Down
Loading

0 comments on commit 4f43a5c

Please sign in to comment.