diff --git a/lib/captp.js b/lib/captp.js index 31f68778524..0fe02c70d1b 100644 --- a/lib/captp.js +++ b/lib/captp.js @@ -8,6 +8,7 @@ import { HandledPromise, E } from '@agoric/eventual-send'; export { E, HandledPromise, Nat, harden }; export function makeCapTP(ourId, send, bootstrapObj = undefined) { + let unplug = false; const { serialize, unserialize } = makeMarshal( // eslint-disable-next-line no-use-before-define serializeSlot, @@ -204,6 +205,9 @@ export function makeCapTP(ourId, send, bootstrapObj = undefined) { // Return a dispatch function. const dispatch = obj => { + if (unplug) { + return false; + } const fn = handler[obj.type]; if (fn) { fn(obj); @@ -212,5 +216,16 @@ export function makeCapTP(ourId, send, bootstrapObj = undefined) { return false; }; - return harden({ dispatch, getBootstrap }); + const disconnected = () => { + unplug = true; + const err = Error(`${ourId} disconnected`); + for (const pr of questions.values()) { + pr.rej(err); + } + for (const pr of imports.values()) { + pr.rej(err); + } + }; + + return harden({ dispatch, getBootstrap, disconnected }); } diff --git a/test/disco.js b/test/disco.js new file mode 100644 index 00000000000..6e9383adef6 --- /dev/null +++ b/test/disco.js @@ -0,0 +1,15 @@ +import { test } from 'tape-promise/tape'; +import { harden, makeCapTP } from '../lib/captp'; + +test('try disconnecting captp', async t => { + try { + const { dispatch, getBootstrap, disconnected } = makeCapTP('us', obj => {}, () => harden({})); + const pr = t.rejects(getBootstrap(), Error, 'rejected after disconnect'); + disconnected(); + await pr; + } catch (e) { + t.isNot(e, e, 'unexpected exception'); + } finally { + t.end(); + } +});