Skip to content

Commit

Permalink
add timeout checking to keeping long running code in check.
Browse files Browse the repository at this point in the history
  • Loading branch information
my8bird committed Nov 14, 2011
1 parent 24a6b17 commit 919ee9e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
3 changes: 2 additions & 1 deletion _sandbox_runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@

try {
loaded_module.runInNewContext({
console: console
console: console,
setTimeout: setTimeout
});
} catch (ex) {
process.send({
Expand Down
26 changes: 18 additions & 8 deletions sandboxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
* This is to prevent the downloaded source from getting into infinite loops and such.
* XXX (not impl)
*/
Sandbox.prototype.runSandboxed = function(code) {
var proc = cp.fork(__dirname + '/_sandbox_runner.js');
Sandbox.prototype.runSandboxed = function(code, timeout) {
var proc = cp.fork(__dirname + '/_sandbox_runner.js'),
timer;

// Connect to be notified of messages
// Messages will be sanitised prior to usage.
Expand All @@ -52,18 +53,27 @@
}
});

// XXX Setup a timeout so that long running code can be killed.

// Detect when the child has finished
proc.addListener('exit', (function(statusCode) {
this.emit('finish', statusCode === 1, proc.errors);
this.emit('finish', proc.timedOut || (statusCode > 0), proc.errors);
}).bind(this));

// The setup is finsihed so pipe in the source code to start things off.
this.emit('start');
return proc.send({
"runCode": code
});
proc.send( {runCode: code });

// set a timer to remind us to kill this proccess if it runs to long
if (timeout) {
timer = setTimeout(function() {
proc.timedOut = true;
proc.errors = proc.errors || [];
proc.errors.push('Timeout exceeded.');

proc.kill();
}, timeout);
}

return proc;
};


Expand Down
21 changes: 13 additions & 8 deletions tests/sandbox_spec.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
sandboxer = require(__dirname + '/../sandboxer.js');



describe('Sandbox', function () {
var box, end_status;
var box, end_status, proc;

// { TEST Helpers
// { Helpers
function waitForSub() {
waitsFor(function() {
return end_status.err !== undefined;
},
'sub script did not finish', // error message if timeout exceeds
200 // milliseconds to wait
100 // milliseconds to wait
);
};

function runCode(codeStr) {
function runCode(codeStr, timeout) {
// run the code async
runs(function() { box.runSandboxed(codeStr); });
runs(function() { proc = box.runSandboxed(codeStr, timeout); });
// wait for it to finish
waitForSub();
};
Expand All @@ -31,7 +30,7 @@ describe('Sandbox', function () {
}
});
};
// END TEST Helpers
// END Helpers

beforeEach(function() {
box = new sandboxer.Sandbox();
Expand All @@ -48,7 +47,7 @@ describe('Sandbox', function () {
});

// TESTS
it("valid code", function () {
it("works with valid code", function () {
runCode('var a = 1;');
assertRanWithError(false);
});
Expand All @@ -59,5 +58,11 @@ describe('Sandbox', function () {
assertRanWithError(true, "SyntaxError: Unexpected string");
});

it("fails if the timeout is passed", function() {
// timeout set to happen after 0.1 seconds but the script will run for a full second.
runCode("setTimeout(function(){var a = 1;}, 1000);", 10);
assertRanWithError(true, "Timeout exceeded.");
});

});

0 comments on commit 919ee9e

Please sign in to comment.