Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
damianofalcioni opened this issue Oct 18, 2024 · 4 comments

Comments

@damianofalcioni
Copy link

damianofalcioni commented Oct 18, 2024

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 damianofalcioni changed the title Error catching interruptions in an async inside returned promise evalCode not catching interruptions for long running async inside a promise Oct 30, 2024
@justjake
Copy link
Owner

Do you have any evidence the loop is actually running inside the promise? For example, if you call a log function in the loop, do you see log output?

@damianofalcioni
Copy link
Author

I'll try and let you know. For now I can only say they it run for exactly the amount of time specified in the interrupt handler. if you change to 10 second it will crash after 10 secods, so I assume the loop is running.

@damianofalcioni
Copy link
Author

I confirm that the log function is called in the loop. Example is updated.

@damianofalcioni
Copy link
Author

latest LTS version of node (v22.11.0) generate a warning before terminating the execution:

Warning: Detected unsettled top-level await at file:///.../testBug.js:73
  const resolvedPromise = await promise;
                          ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants