nightcod3r
nightcod3r

Reputation: 792

Time limit for code execution

Considering the following execution of a JS program in a JS settlement, how can I implement a time limit to prevent infinite loops in program?

try {
  var x = eval(document.getElementById("program").value);
} catch(e) {
  ...
}

Note: the call should be able to specify a maximum execution time, just in case program enters an infinite loop.

Upvotes: 1

Views: 285

Answers (1)

Jonas Wilms
Jonas Wilms

Reputation: 138447

You could use a webworker to run this in another thread:

// Worker-helper.js
self.onmessage = function(e) {
  self.postMessage(eval(e.data));
};

Them use the worker as:

var worker = new Worker('Worker-helper.js');
worker.postMessage(document.getElementById("program").value);

worker.onmessage = result => {
  alert(result);
};

setTimeout(() => worker.terminate(), 10 * 1000);

...which will kill the worker after 10 seconds.


Easy to use utility:

function funToWorker(fn) {
  var response = "(" + fn.toString() + ")()";
  var blob;
  try {
    blob = new Blob([response], {type:  'application/javascript'});
   } catch (e) { // Backwards-compatibility
     window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
     blob = new BlobBuilder();
     blob.append(response);
    blob = blob.getBlob();
   }

   return new Worker(URL.createObjectURL(blob));
 }

 function limitedEval(string, timeout) {
   return new Promise((resolve, reject) => {
     const worker = funToWorker(function() {
        self.onmessage = e => {
          self.postMessage(eval(e.data));
        }
     });

     worker.onmessage = e => resolve(e.data);
     worker.postMessage(string);
    setTimeout(() => {
       worker.terminate();
       reject();
    }, timeout);
  });
}

Usable as:

 limitedEval("1 + 2", 1000)
    .then(console.log)
    .catch(console.error);

Try it!

Upvotes: 1

Related Questions