@@ -60,7 +60,9 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
60
60
const logStartup = verbose ? console . debug : ( ) => 0 ;
61
61
62
62
insistStorageAPI ( hostStorage ) ;
63
- const { enhancedCrankBuffer, commitCrank } = wrapStorage ( hostStorage ) ;
63
+ const { enhancedCrankBuffer, abortCrank, commitCrank } = wrapStorage (
64
+ hostStorage ,
65
+ ) ;
64
66
65
67
const kernelSlog = writeSlogObject
66
68
? makeSlogger ( writeSlogObject )
@@ -283,6 +285,36 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
283
285
}
284
286
}
285
287
288
+ function removeVatManager ( vatID , reason ) {
289
+ const old = ephemeral . vats . get ( vatID ) ;
290
+ ephemeral . vats . delete ( vatID ) ;
291
+ const err = reason ? Error ( reason ) : undefined ;
292
+ old . notifyTermination ( err ) ; // XXX TODO: most of the places where notifyTermination gets passed don't need it
293
+ return old . manager . shutdown ( ) ;
294
+ }
295
+
296
+ function terminateVat ( vatID , reason ) {
297
+ if ( kernelKeeper . getVatKeeper ( vatID ) ) {
298
+ const promisesToReject = kernelKeeper . cleanupAfterTerminatedVat ( vatID ) ;
299
+ const err = reason ? makeError ( reason ) : VAT_TERMINATION_ERROR ;
300
+ for ( const kpid of promisesToReject ) {
301
+ resolveToError ( kpid , err , vatID ) ;
302
+ }
303
+ removeVatManager ( vatID , reason ) . then (
304
+ ( ) => kdebug ( `terminated vat ${ vatID } ` ) ,
305
+ e => console . error ( `problem terminating vat ${ vatID } ` , e ) ,
306
+ ) ;
307
+ }
308
+ }
309
+
310
+ let deliveryProblem ;
311
+
312
+ function registerDeliveryProblem ( vatID , problem , resultKP ) {
313
+ if ( ! deliveryProblem ) {
314
+ deliveryProblem = { vatID, problem, resultKP } ;
315
+ }
316
+ }
317
+
286
318
async function deliverAndLogToVat ( vatID , kernelDelivery , vatDelivery ) {
287
319
const vat = ephemeral . vats . get ( vatID ) ;
288
320
const crankNum = kernelKeeper . getCrankNumber ( ) ;
@@ -295,10 +327,10 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
295
327
try {
296
328
const deliveryResult = await vat . manager . deliver ( vatDelivery ) ;
297
329
finish ( deliveryResult ) ;
298
- // TODO: eventually
299
- // if (deliveryResult === death ) {
300
- // vat.notifyTermination(deliveryResult.causeOfDeath );
301
- // }
330
+ const [ status , problem ] = deliveryResult ;
331
+ if ( status !== 'ok' ) {
332
+ registerDeliveryProblem ( vatID , problem ) ;
333
+ }
302
334
} catch ( e ) {
303
335
// log so we get a stack trace
304
336
console . error ( `error in kernel.deliver:` , e ) ;
@@ -426,6 +458,7 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
426
458
}
427
459
try {
428
460
processQueueRunning = Error ( 'here' ) ;
461
+ deliveryProblem = null ;
429
462
if ( message . type === 'send' ) {
430
463
kernelKeeper . decrementRefCount ( message . target , `deq|msg|t` ) ;
431
464
kernelKeeper . decrementRefCount ( message . msg . result , `deq|msg|r` ) ;
@@ -441,8 +474,15 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
441
474
} else {
442
475
throw Error ( `unable to process message.type ${ message . type } ` ) ;
443
476
}
444
- kernelKeeper . purgeDeadKernelPromises ( ) ;
445
- kernelKeeper . saveStats ( ) ;
477
+ if ( deliveryProblem ) {
478
+ abortCrank ( ) ;
479
+ const { vatID, problem } = deliveryProblem ;
480
+ terminateVat ( vatID , problem ) ;
481
+ kdebug ( `vat abnormally terminated: ${ problem } ` ) ;
482
+ } else {
483
+ kernelKeeper . purgeDeadKernelPromises ( ) ;
484
+ kernelKeeper . saveStats ( ) ;
485
+ }
446
486
commitCrank ( ) ;
447
487
kernelKeeper . incrementCrankNumber ( ) ;
448
488
} finally {
@@ -639,19 +679,20 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
639
679
// This is a safety check -- this case should never happen unless the
640
680
// vatManager is somehow confused.
641
681
console . error ( `vatSyscallHandler invoked on dead vat ${ vatID } ` ) ;
642
- return harden ( [ 'error' , 'vat is dead' ] ) ;
682
+ const problem = 'vat is dead' ;
683
+ registerDeliveryProblem ( vatID , problem ) ;
684
+ return harden ( [ 'error' , problem ] ) ;
643
685
}
644
686
let ksc ;
645
687
try {
646
688
// this can fail if the vat asks for something not on their clist,
647
689
// which is fatal to the vat
648
690
ksc = translators . vatSyscallToKernelSyscall ( vatSyscallObject ) ;
649
691
} catch ( vaterr ) {
650
- console . error ( `vat ${ vatID } error during translation: ${ vaterr } ` ) ;
651
- console . error ( `vat terminated` ) ;
652
- // TODO: mark the vat as dead, reject subsequent syscalls, withhold
653
- // deliveries, notify adminvat
654
- return harden ( [ 'error' , 'clist violation: prepare to die' ] ) ;
692
+ kdebug ( `vat ${ vatID } terminated: error during translation: ${ vaterr } ` ) ;
693
+ const problem = 'clist violation: prepare to die' ;
694
+ registerDeliveryProblem ( vatID , problem ) ;
695
+ return harden ( [ 'error' , problem ] ) ;
655
696
}
656
697
657
698
const finish = kernelSlog . syscall ( vatID , ksc , vatSyscallObject ) ;
@@ -674,7 +715,9 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
674
715
panic ( `error during syscall/device.invoke: ${ err } ` , err ) ;
675
716
// the kernel is now in a shutdown state, but it may take a while to
676
717
// grind to a halt
677
- return harden ( [ 'error' , 'you killed my kernel. prepare to die' ] ) ;
718
+ const problem = 'you killed my kernel. prepare to die' ;
719
+ registerDeliveryProblem ( vatID , problem ) ;
720
+ return harden ( [ 'error' , problem ] ) ;
678
721
}
679
722
680
723
return vres ;
@@ -717,13 +760,6 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
717
760
manager . setVatSyscallHandler ( vatSyscallHandler ) ;
718
761
}
719
762
720
- function removeVatManager ( vatID ) {
721
- const old = ephemeral . vats . get ( vatID ) ;
722
- ephemeral . vats . delete ( vatID ) ;
723
- old . notifyTermination ( null ) ;
724
- return old . manager . shutdown ( ) ;
725
- }
726
-
727
763
const knownBundles = new Map ( ) ;
728
764
729
765
function hasBundle ( name ) {
@@ -843,19 +879,6 @@ export default function buildKernel(kernelEndowments, kernelOptions = {}) {
843
879
// now the vatManager is attached and ready for transcript replay
844
880
}
845
881
846
- function terminateVat ( vatID ) {
847
- if ( kernelKeeper . getVatKeeper ( vatID ) ) {
848
- const promisesToReject = kernelKeeper . cleanupAfterTerminatedVat ( vatID ) ;
849
- for ( const kpid of promisesToReject ) {
850
- resolveToError ( kpid , VAT_TERMINATION_ERROR , vatID ) ;
851
- }
852
- removeVatManager ( vatID ) . then (
853
- ( ) => kdebug ( `terminated vat ${ vatID } ` ) ,
854
- e => console . error ( `problem terminating vat ${ vatID } ` , e ) ,
855
- ) ;
856
- }
857
- }
858
-
859
882
if ( vatAdminDeviceBundle ) {
860
883
// if we have a device bundle, then vats[vatAdmin] will be present too
861
884
const endowments = {
0 commit comments