Browse Source

child_process_uv: add exec, fix simple/test-child-process-exec-cwd

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
19a62589b2
  1. 5
      Makefile
  2. 119
      lib/child_process_uv.js
  3. 2
      src/process_wrap.cc
  4. 29
      test/simple/test-child-process-exec-env.js

5
Makefile

@ -234,8 +234,9 @@ UVTEST += simple/test-tls-request-timeout
UVTEST += simple/test-tls-set-encoding UVTEST += simple/test-tls-set-encoding
# child_process # child_process
UVTEST += simple/test-child-process-exit-code.js UVTEST += simple/test-child-process-exit-code
UVTEST += simple/test-child-process-buffering.js UVTEST += simple/test-child-process-buffering
UVTEST += simple/test-child-process-exec-cwd
test-uv: all test-uv: all

119
lib/child_process_uv.js

@ -47,6 +47,125 @@ function createSocket(pipe, readable) {
} }
exports.exec = function(command /*, options, callback */) {
var rest = Array.prototype.slice.call(arguments, 1);
var args = ['/bin/sh', ['-c', command]].concat(rest);
return exports.execFile.apply(this, args);
};
exports.execFile = function(file /* args, options, callback */) {
var args, optionArg, callback;
var options = {
encoding: 'utf8',
timeout: 0,
maxBuffer: 200 * 1024,
killSignal: 'SIGTERM',
setsid: false,
cwd: null,
env: null
};
// Parse the parameters.
if (typeof arguments[arguments.length - 1] === 'function') {
callback = arguments[arguments.length - 1];
}
if (Array.isArray(arguments[1])) {
args = arguments[1];
if (typeof arguments[2] === 'object') optionArg = arguments[2];
} else {
args = [];
if (typeof arguments[1] === 'object') optionArg = arguments[1];
}
// Merge optionArg into options
if (optionArg) {
var keys = Object.keys(options);
for (var i = 0, len = keys.length; i < len; i++) {
var k = keys[i];
if (optionArg[k] !== undefined) options[k] = optionArg[k];
}
}
var child = spawn(file, args, {
cwd: options.cwd,
env: options.env
});
var stdout = '';
var stderr = '';
var killed = false;
var exited = false;
var timeoutId;
var err;
function exithandler(code, signal) {
if (exited) return;
exited = true;
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (!callback) return;
if (err) {
callback(err, stdout, stderr);
} else if (code === 0 && signal === null) {
callback(null, stdout, stderr);
} else {
var e = new Error('Command failed: ' + stderr);
e.killed = child.killed || killed;
e.code = code;
e.signal = signal;
callback(e, stdout, stderr);
}
}
function kill() {
killed = true;
child.kill(options.killSignal);
process.nextTick(function() {
exithandler(null, options.killSignal);
});
}
if (options.timeout > 0) {
timeoutId = setTimeout(function() {
kill();
timeoutId = null;
}, options.timeout);
}
child.stdout.setEncoding(options.encoding);
child.stderr.setEncoding(options.encoding);
child.stdout.addListener('data', function(chunk) {
stdout += chunk;
if (stdout.length > options.maxBuffer) {
err = new Error('maxBuffer exceeded.');
kill();
}
});
child.stderr.addListener('data', function(chunk) {
stderr += chunk;
if (stderr.length > options.maxBuffer) {
err = new Error('maxBuffer exceeded.');
kill();
}
});
child.addListener('exit', exithandler);
return child;
};
var spawn = exports.spawn = function(file, args, options) { var spawn = exports.spawn = function(file, args, options) {
var child = new ChildProcess(); var child = new ChildProcess();

2
src/process_wrap.cc

@ -106,7 +106,7 @@ class ProcessWrap : public HandleWrap {
// options.cwd // options.cwd
Local<Value> cwd_v = js_options->Get(String::New("cwd")); Local<Value> cwd_v = js_options->Get(String::New("cwd"));
if (!cwd_v.IsEmpty() && cwd_v->IsString()) { if (!cwd_v.IsEmpty() && cwd_v->IsString()) {
String::Utf8Value cwd(js_options->ToString()); String::Utf8Value cwd(cwd_v->ToString());
options.cwd = strdup(*cwd); options.cwd = strdup(*cwd);
} }

29
test/simple/test-child-process-exec-env.js

@ -26,27 +26,28 @@ var success_count = 0;
var error_count = 0; var error_count = 0;
var response = ''; var response = '';
var child = exec('/usr/bin/env', {env: {'HELLO': 'WORLD'}}, function after(err, stdout, stderr) {
function(err, stdout, stderr) { if (err) {
if (err) { error_count++;
error_count++; console.log('error!: ' + err.code);
console.log('error!: ' + err.code); console.log('stdout: ' + JSON.stringify(stdout));
console.log('stdout: ' + JSON.stringify(stdout)); console.log('stderr: ' + JSON.stringify(stderr));
console.log('stderr: ' + JSON.stringify(stderr)); assert.equal(false, err.killed);
assert.equal(false, err.killed); } else {
} else { success_count++;
success_count++; assert.equal(true, stdout != '');
assert.equal(true, stdout != ''); }
} }
});
child.stdout.setEncoding('utf8'); var child = exec('/usr/bin/env', { env: { 'HELLO': 'WORLD' } }, after);
child.stdout.setEncoding('utf8');
child.stdout.addListener('data', function(chunk) { child.stdout.addListener('data', function(chunk) {
response += chunk; response += chunk;
}); });
process.addListener('exit', function() { process.addListener('exit', function() {
console.log("response: ", response);
assert.equal(1, success_count); assert.equal(1, success_count);
assert.equal(0, error_count); assert.equal(0, error_count);
assert.ok(response.indexOf('HELLO=WORLD') >= 0); assert.ok(response.indexOf('HELLO=WORLD') >= 0);

Loading…
Cancel
Save