Skip to content

evalCode not catching interruptions for long running async inside a promise #211

@damianofalcioni

Description

@damianofalcioni

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions