2017-11-22 111 views
7

Normal olarak C++ execl iyi çalışıyor (g++ ok.cc -o ok.elf ile derleme)execl C++ node.js-addon kilitleniyor

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

Ama çöküyorsa, node.js C++ addon olarak çalışıldığında

#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) 
} 

Crash of node.js extension

node.js v8.9.1
düğüm -gec v3.6.2
gcc sürümü 6.3.0 20170406 (Ubuntu 6.3.0-12ubuntu2)

+0

Evet, biliyorum bu işlem işlem belleği temsilinin yerini alır. Başlangıçta, fork() 'syscall –

+1

Node ile çocuk süreçleri oluşturmak için kullanıyorum Node, tüm posix syscall'larını desteklemiyor. Bu konuya bakın https://stackoverflow.com/questions/34290403/a-way-to-call-execl-execle-execlp-execv-execvp-or-execvp-from-node-js. Sizin için uygun olmayan bir şey kullandığınız için çökme bekleniyor –

cevap

1

Düğüm, tüm posix syscall öğelerini desteklemez.

Bu konuyu size yapılabilecek olmayan bir şey kullandığınız olarak kazasında beklenen

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

bakınız. Yukarıdaki iplik tartışıldığı gibi sen

index.cc kendi exec

#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 oluşturma amacıyla gerekir: Kod içinde, https://github.com/OrKoN/native-exec yayınlandıkça Büyük/küçük harf kullanımı, gelecekte başka bir şeyde etkin olmayacaktır. Yapmaya çalışmamalısınız, TTY'yi alması gereken bir şey yürütmek, bu durumda çok fazla karmaşıklık katacaksınız. Bu yüzden çalışan python'un TTY'nizi kontrol altına alması gerekecektir.

İlgili konular