quickjs-emscripten icon indicating copy to clipboard operation
quickjs-emscripten copied to clipboard

evalCode not catching interruptions for long running async inside a promise

Open damianofalcioni opened this issue 1 year ago • 4 comments
trafficstars

Hi, I have the following code that is not able to capture the interruption and terminate Node with error code 13:

import { getQuickJS, shouldInterruptAfterDeadline } from 'quickjs-emscripten';

const QuickJS = await getQuickJS();
const runtime = QuickJS.newRuntime();
runtime.setInterruptHandler(shouldInterruptAfterDeadline(Date.now() + 1000));
const vm = runtime.newContext();
vm.newFunction('log', ()=>console.log('loop')).consume((fnHandle) => vm.setProp(vm.global, 'log', fnHandle));

try {

  //Sample 1: Node print loop for 1s then terminate with error code 13 without throwing exceptions 
  const result = vm.unwrapResult(vm.evalCode(`
  new Promise((out, err) => {
    (async ()=>{
      while(1){ log(); }
      out('ok');
    })();
  });
  `));

/*
  //Sample 2: Same error of Sample 1
  const result = vm.unwrapResult(vm.evalCode(`
  new Promise(async (out, err) => {
    while(1){ log(); }
    out('ok');
  });
  `));
*/
/*
  //Sample 3: Same error of Sample 1
  const result = vm.unwrapResult(vm.evalCode(`
    new Promise((out1, err1) => {
      new Promise((out2, err2) => {
        while(1){}
        out1('ok');
      });
    });
  `));
*/
/*
  //Sample 4: Here the interruption is catched correctly
  const result = vm.unwrapResult(vm.evalCode(`
  (async ()=>{
    while(1){}
    return 'ok';
  })();
  `));
*/

/*
  //Sample 5: Here the interruption is catched correctly
  const result = vm.unwrapResult(vm.evalCode(`
  new Promise((out, err) => {
    while(1){}
    out('ok');
  });
  `));
*/
/*
  //Sample 6: Here the interruption is catched correctly
  const result = vm.unwrapResult(vm.evalCode(`
  (async ()=>{
    await (async ()=>{
      while(1){}
    })();
    return 'ok';
  })();
  `));
*/
  const promise = result.consume(result=>vm.resolvePromise(result));
  vm.runtime.executePendingJobs();
  const resolvedPromise = await promise;
  if (resolvedPromise.error) {
    //never reached on sample 1, 2, and 3
    console.log(vm.dump(resolvedPromise.error));
    resolvedPromise.error.dispose();
  }else{
    console.log(vm.dump(resolvedPromise.value));
    resolvedPromise.value.dispose();
  }
} catch(e) {
  //never reached
  console.error(e);
} finally {
  vm.dispose();
}
//never reached on sample 1, 2, and 3
console.log('end');

as you see it happen only when the loop is inside an async function or a promise inside another promise. Note that everything work if the loop is removed. Any suggestion? Thanks

quickjs-emscripten v0.31.0

damianofalcioni avatar Oct 18 '24 14:10 damianofalcioni