0

I am currently looking for a way to timeout on a synchonous JavaScript code using node.

In a nutshell: I have a synchronous code which takes too long (for instance: an infinite loop). I would be interesting in stopping its run.

On async function

I found a way to do it on asynchronous calls using Promise.race with a custom delay promise which ends after Xxx milliseconds. For asynchronous functions the code is the following:

    function timeoutIt(fun, timeMs) {
        return Promise.race([
            fun(),
            new Promise((resolve, reject) => setTimeout(reject, timeMs))
        ]);
    }

I tried to derive this snippet to receive my synchronous function, but once the function has been called the reject Promise is never executed. Any idea to have some kind of timeout on synchronous code?

Context: I am currently working on a property based testing framework https://github.com/dubzzz/fast-check and wanted to be able to work even for disruptive cases where the code goes into infinite loops. For the moment, the code holds and wait for the test framework to timeout on its side

Thanks in advance for your help

1
  • Not 100% sure but think you can run child process with the timeout parameter. Commented Feb 10, 2018 at 18:10

1 Answer 1

1

In your example the reject function doesn't work because javascript is single threaded.

In reality, the setTimeout function is working, but runs outside of the javascript thread(in browser queue system, or in your case by the node.js queue system (libuv), when setTimeout finished, the handler (the code you want to execute when the timeout finish) is inserted in a event queue and prepared to be executed for javascript throught the event loop, but, the problem is that the event loop is processing the code of your synchronous code, and never reach your handler.

This is an "homemade" example to stops a infite loop:

function longTimeFunction(timeAllowedInSeconds) {
    function getCurrentTime() {
        return new Date().getTime() / 1000;
    }

    const startTime = getCurrentTime();
    let stopLoop = false;
    let currentTime;

    while(1 && !stopLoop) {  //infinite loop
        //your code here, for example:
        console.log(Math.random());

        currentTime = Math.round(getCurrentTime() - startTime);

        if (currentTime >= timeAllowedInSeconds) {
            stopLoop = true;
        }
    }
};

longTimeFunction(3);

To help you understand the how deal with sync and async in javascript I put here one amazing video:

Philip Roberts: What the heck is the event loop anyway? | JSConf EU 2014

Sign up to request clarification or add additional context in comments.

6 Comments

Indeed, it is totally logical, due to its single-threaded property, that while the blocking code is running nothing can stop it except it self.
I was just wondering if there was some kind of built-in feature of the JavaScript or Node flags or options to prevent a synchronous code from running too long.
I believe that Mocha, for instance, succeed in stopping long scripts but I don't know how it does: does it fork other processes? does it transform the code by translating for-loops with setTimeout (not really possible)? does it runs in a custom node?
Sorry DubZzz I don't know how works Mocha, I have been watching a bit the lib (Runner.js, Runnable.js and others files of the library) github.com/mochajs/mocha/tree/master/lib Hope that helps in some way
Thanks for the comment, I will have a look to their implementation and come back to this thread as soon as I get an understanding of how they manage to do this.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.