Execl crash c ++ node.js-addon

As usual, C ++ execl works fine (compiling with g++ ok.cc -o ok.elf )

 #include <unistd.h> int main(){ execl("/usr/bin/python", "/usr/bin/python", nullptr); } 

But crash when it works like node.js c ++ addon

 #include <node.h> #include <unistd.h> namespace bug{ void wtf(const v8::FunctionCallbackInfo<v8::Value>& args){ execl("/usr/bin/python", "/usr/bin/python", nullptr); } void init(v8::Local<v8::Object> exports){ NODE_SET_METHOD(exports, "wtf", bug::wtf); } NODE_MODULE(NODE_GYP_MODULE_NAME, init) } 

Node.js extension failed

node.js v8.9.1
node -gyp v3.6.2
6.3.0 20170406 (Ubuntu 6.3.0-12ubuntu2) version 6.3.0 20170406 (Ubuntu 6.3.0-12ubuntu2)

+7
linux crash node.js-addon
source share
1 answer

Node does not support all sixall posix.

See this topic

How to call execl, execle, execlp, execv, execvP or execvp from Node.js

Crash is expected, as you are using something that is not available to you. As discussed in the thread above, you need to either create your own exec

index.cc

 #include <nan.h> #include <fcntl.h> #include <unistd.h> int doNotCloseStreamsOnExit(int desc) { int flags = fcntl(desc, F_GETFD, 0); if (flags < 0) return flags; flags &= ~FD_CLOEXEC; //clear FD_CLOEXEC bit return fcntl(desc, F_SETFD, flags); } void copyArray(char* dest[], unsigned int offset, v8::Local<v8::Array> src) { unsigned int length = src->Length(); for (unsigned int i = 0; i < length; i++) { v8::String::Utf8Value arrayElem(Nan::Get(src, i).ToLocalChecked()->ToString()); std::string arrayElemStr (*arrayElem); char* tmp = new char[arrayElemStr.length() +1]; strcpy(tmp, arrayElemStr.c_str()); dest[i + offset] = tmp; } } void setEnv(v8::Local<v8::Array> src) { unsigned int length = src->Length(); v8::Local<v8::String> keyProp = Nan::New<v8::String>("key").ToLocalChecked(); v8::Local<v8::String> valueProp = Nan::New<v8::String>("value").ToLocalChecked(); for (unsigned int i = 0; i < length; i++) { v8::Local<v8::Object> obj = Nan::Get(src, i).ToLocalChecked()->ToObject(); v8::String::Utf8Value objKey(Nan::Get(obj, keyProp).ToLocalChecked()->ToString()); v8::String::Utf8Value objValue(Nan::Get(obj, valueProp).ToLocalChecked()->ToString()); std::string objKeyStr (*objKey); char *key = const_cast<char*> ( objKeyStr.c_str() ); std::string objValueStr (*objValue); char *value = const_cast<char*> ( objValueStr.c_str() ); setenv(key, value, 1); } } void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) { if (info.Length() < 3) { return; } if (!info[0]->IsString()) { return; } // get command v8::String::Utf8Value val(info[0]->ToString()); std::string str (*val); char *command = const_cast<char*> ( str.c_str() ); // set env on the current process v8::Local<v8::Array> envArr = v8::Local<v8::Array>::Cast(info[1]); setEnv(envArr); // build args: command, ...args, NULL v8::Local<v8::Array> argsArr = v8::Local<v8::Array>::Cast(info[2]); char* args[argsArr->Length() + 2]; args[0] = command; copyArray(args, 1, argsArr); args[argsArr->Length() + 1] = NULL; // fix stream flags doNotCloseStreamsOnExit(0); //stdin doNotCloseStreamsOnExit(1); //stdout doNotCloseStreamsOnExit(2); //stderr execvp(command, args); } void Init(v8::Local<v8::Object> exports) { exports->Set(Nan::New("exec").ToLocalChecked(), Nan::New<v8::FunctionTemplate>(Method)->GetFunction()); } NODE_MODULE(exec, Init) 

index.js

 'use strict'; var addon = require('bindings')('addon'); var path = require('path'); var fs = require('fs'); module.exports = function(cmd, env, args) { if (!cmd) { throw new Error('Command is required'); } var envArr = Object.keys(env || {}).map(key => { return { key, value: env[key], }; }); addon.exec(cmd, envArr, args || []); }; 

PS: The code was sent from https://github.com/OrKoN/native-exec if the link is inactive in the future

Another thing you should not try to do is do something to get the TTY, in which case you will add a lot of complexity. Thus, python startup will have to control your TTY.

+1
source share

All Articles