diff --git a/lib/child_process.js b/lib/child_process.js index c6a2a94bc5..3355b8ab28 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -165,7 +165,7 @@ function nop() { } exports.fork = function(modulePath /*, args, options*/) { // Get options and args arguments. - var options, args; + var options, args, execArgv; if (Array.isArray(arguments[1])) { args = arguments[1]; options = arguments[2] || {}; @@ -174,9 +174,9 @@ exports.fork = function(modulePath /*, args, options*/) { options = arguments[1] || {}; } - // Copy args and add modulePath - args = args.slice(0); - args.unshift(modulePath); + // Prepare arguments for fork: + execArgv = options.execArgv || process.execArgv; + args = execArgv.concat([modulePath], args); // Don't allow stdinStream and customFds since a stdin channel will be used if (options.stdinStream) { diff --git a/lib/cluster.js b/lib/cluster.js index 556ab67fd8..cd90219bfd 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -91,6 +91,7 @@ cluster.setupMaster = function(options) { // Set settings object settings = cluster.settings = { exec: options.exec || process.argv[1], + execArgv: options.execArgv || process.execArgv, args: options.args || process.argv.slice(2), silent: options.silent || false }; @@ -274,7 +275,8 @@ function Worker(customEnv) { // fork worker this.process = fork(settings.exec, settings.args, { 'env': envCopy, - 'silent': settings.silent + 'silent': settings.silent, + 'execArgv': settings.execArgv }); } else { this.process = process; diff --git a/src/node.cc b/src/node.cc index df9e4fd856..dcc2249d8a 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2126,6 +2126,15 @@ Handle SetupProcessObject(int argc, char *argv[]) { // assign it process->Set(String::NewSymbol("argv"), arguments); + // process.execArgv + Local execArgv = Array::New(option_end_index - 1); + for (j = 1, i = 0; j < option_end_index; j++, i++) { + execArgv->Set(Integer::New(i), String::New(argv[j])); + } + // assign it + process->Set(String::NewSymbol("execArgv"), execArgv); + + // create process.env Local envTemplate = ObjectTemplate::New(); envTemplate->SetNamedPropertyHandler(EnvGetter, @@ -2713,10 +2722,45 @@ void EmitExit(v8::Handle process_l) { } } +static char **copy_argv(int argc, char **argv) { + size_t strlen_sum; + char **argv_copy; + char *argv_data; + size_t len; + int i; + + strlen_sum = 0; + for(i = 0; i < argc; i++) { + strlen_sum += strlen(argv[i]) + 1; + } + + argv_copy = (char **) malloc(sizeof(char *) * (argc + 1) + strlen_sum); + if (!argv_copy) { + return NULL; + } + + argv_data = (char *) argv_copy + sizeof(char *) * (argc + 1); + + for(i = 0; i < argc; i++) { + argv_copy[i] = argv_data; + len = strlen(argv[i]) + 1; + memcpy(argv_data, argv[i], len); + argv_data += len; + } + + argv_copy[argc] = NULL; + + return argv_copy; +} int Start(int argc, char *argv[]) { + // Logic to duplicate argv as Init() modifies arguments + // that are passed into it. + char **argv_copy = copy_argv(argc, argv); + // This needs to run *before* V8::Initialize() - argv = Init(argc, argv); + // Use copy here as to not modify the original argv: + Init(argc, argv_copy); V8::Initialize(); Persistent context; @@ -2728,6 +2772,7 @@ int Start(int argc, char *argv[]) { Persistent context = Context::New(); Context::Scope context_scope(context); + // Use original argv, as we're just copying values out of it. Handle process_l = SetupProcessObject(argc, argv); v8_typed_array::AttachBindings(context->Global()); @@ -2753,6 +2798,9 @@ int Start(int argc, char *argv[]) { V8::Dispose(); #endif // NDEBUG + // Clean up the copy: + free(argv_copy); + return 0; }