Skip to content

Commit

Permalink
fix(swingset): delay snapshot tmp deletion rather than eval null
Browse files Browse the repository at this point in the history
  • Loading branch information
dckc committed Jun 29, 2021
1 parent 628ef14 commit d13046d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 13 deletions.
19 changes: 17 additions & 2 deletions packages/SwingSet/src/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,23 @@ export function makeStartXSnap(bundles, { snapStore, env, spawn }) {
// console.log('startXSnap from', { snapshotHash });
return snapStore.load(snapshotHash, async snapshot => {
const xs = doXSnap({ snapshot, name, handleCommand, ...xsnapOpts });
await xs.evaluate('null'); // ensure that spawn is done
return xs;
// TMP KLUDGE: wrap evaluate, issueCommand to remove tmp file. :-/
const evaluate = async code => {
const out = await xs.evaluate(code);
await snapStore.unlink(snapshot);
return out;
};
const issueCommand = async bytes => {
const out = await xs.issueCommand(bytes);
await snapStore.unlink(snapshot);
return out;
};
const issueStringCommand = async str => {
const out = await xs.issueStringCommand(str);
await snapStore.unlink(snapshot);
return out;
};
return { ...xs, evaluate, issueCommand, issueStringCommand };
});
}
// console.log('fresh xsnap', { snapStore: snapStore });
Expand Down
20 changes: 10 additions & 10 deletions packages/xsnap/src/snapStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,16 @@ export function makeSnapStore(
* @template T
*/
async function load(hash, loadRaw) {
return withTempName(async raw => {
await filter(resolve(root, `${hash}.gz`), createGunzip(), raw);
const actual = await fileHash(raw);
// console.log('load', { raw, hash });
assert(actual === hash, d`actual hash ${actual} !== expected ${hash}`);
// be sure to await loadRaw before exiting withTempName
const result = await loadRaw(raw);
return result;
}, `${hash}-load`);
const raw = await ptmpName({
tmpdir: root,
template: `${hash}-load-XXXXXX.xss`,
keep: true,
});
await filter(resolve(root, `${hash}.gz`), createGunzip(), raw);
const actual = await fileHash(raw);
assert(actual === hash, d`actual hash ${actual} !== expected ${hash}`);
return loadRaw(raw);
}

return freeze({ load, save });
return freeze({ load, save, unlink });
}
58 changes: 57 additions & 1 deletion packages/xsnap/test/test-snapstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import test from 'ava';
import tmp from 'tmp';
import { xsnap } from '../src/xsnap.js';
import { makeSnapStore } from '../src/snapStore.js';
import { loader } from './message-tools.js';
import { options, loader } from './message-tools.js';

const importMeta = { url: `file://${__filename}` };
const ld = loader(importMeta.url, fs.promises.readFile); // WARNING: ambient
const io = { spawn, os: osType() }; // WARNING: ambien

/**
* @param {string} name
Expand Down Expand Up @@ -176,3 +177,58 @@ test.failing('XS + SES snapshots should be deterministic', t => {
const h = 'abc';
t.is('66244b4bfe92ae9138d24a9b50b492d231f6a346db0cf63543d200860b423724', h);
});

test('load many snapshots', async t => {
const pool = tmp.dirSync({ unsafeCleanup: true });
t.log({ pool });
//t.teardown(() => pool.removeCallback());

const store = makeSnapStore(pool.name, {
...tmp,
...path,
...fs,
...fs.promises,
});

const names = Array.from(Array(3).keys()).map(n => `vat${n}`);
const savedHashes = await Promise.all(
names.map(async name => {
// t.log({ name });
const worker = xsnap({ ...options(io), name });
t.teardown(() => worker.terminate());
await worker.evaluate(`
globalThis.send = it => issueCommand(ArrayBuffer.fromString(it));
globalThis.name = "${name}";
`);
const h = await store.save(async fn => {
// t.log({ fn });
await worker.snapshot(fn);
});
await worker.close();
return h;
}),
);
t.log({ savedHashes });
const loadedNames = await Promise.all(
savedHashes.map(async hash => {
const opts = options(io);
const worker = await store.load(hash, async snapshot => {
// t.log({ snapshot });
const xs = xsnap({ ...opts, snapshot });
// TMP KLUDGE: wrap evaluate, issueCommand to remove tmp file. :-/
const evaluate = async code => {
const out = await xs.evaluate(code);
await store.unlink(snapshot);
return out;
};
return { ...xs, evaluate };
});
t.teardown(() => worker.terminate());

await worker.evaluate(`send(name)`);
await worker.close();
return opts.messages[0];
}),
);
t.deepEqual(names, loadedNames);
});

0 comments on commit d13046d

Please sign in to comment.