mirror of https://gitee.com/bigwinds/arangodb
Add a new wrapper which does fork + waitpid in one js call, so we're closer to the flame and less eventually miss something.
This commit is contained in:
parent
cd2e386a19
commit
e433a2831e
|
@ -17,8 +17,9 @@
|
|||
COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION,
|
||||
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
|
||||
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
|
||||
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL,
|
||||
SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT, SYS_IS_IP */
|
||||
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_EXECUTE_EXTERNAL_AND_WAIT,
|
||||
SYS_KILL_EXTERNAL, SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT,
|
||||
SYS_IS_IP */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief module "internal"
|
||||
|
@ -689,6 +690,20 @@
|
|||
delete SYS_EXECUTE_EXTERNAL;
|
||||
}
|
||||
|
||||
if (typeof SYS_EXECUTE_EXTERNAL_AND_WAIT !== "undefined") {
|
||||
exports.executeExternalAndWait = SYS_EXECUTE_EXTERNAL_AND_WAIT;
|
||||
delete SYS_EXECUTE_EXTERNAL_AND_WAIT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executeExternalAndWait - instantly waits for the exit, returns
|
||||
/// joint result.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
if (typeof SYS_EXECUTE_EXTERNAL_AND_WAIT !== "undefined") {
|
||||
exports.executeExternalAndWait = SYS_EXECUTE_EXTERNAL_AND_WAIT;
|
||||
delete SYS_EXECUTE_EXTERNAL_AND_WAIT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief killExternal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION,
|
||||
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
|
||||
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
|
||||
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL,
|
||||
SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT, SYS_IS_IP */
|
||||
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_EXECUTE_EXTERNAL_AND_WAIT,
|
||||
SYS_KILL_EXTERNAL, SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT,
|
||||
SYS_IS_IP */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief module "internal"
|
||||
|
@ -689,6 +690,15 @@
|
|||
delete SYS_EXECUTE_EXTERNAL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executeExternalAndWait - instantly waits for the exit, returns
|
||||
/// joint result.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
if (typeof SYS_EXECUTE_EXTERNAL_AND_WAIT !== "undefined") {
|
||||
exports.executeExternalAndWait = SYS_EXECUTE_EXTERNAL_AND_WAIT;
|
||||
delete SYS_EXECUTE_EXTERNAL_AND_WAIT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief killExternal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -93,6 +93,7 @@ var wait = require("internal").wait;
|
|||
var executeExternal = require("internal").executeExternal;
|
||||
var killExternal = require("internal").killExternal;
|
||||
var statusExternal = require("internal").statusExternal;
|
||||
var executeExternalAndWait = require("internal").executeExternalAndWait;
|
||||
var base64Encode = require("internal").base64Encode;
|
||||
|
||||
var PortFinder = require("org/arangodb/cluster").PortFinder;
|
||||
|
@ -398,9 +399,8 @@ function runThere (options, instanceInfo, file) {
|
|||
}
|
||||
|
||||
function executeAndWait (cmd, args) {
|
||||
var pid = executeExternal(cmd, args);
|
||||
var startTime = time();
|
||||
var res = statusExternal(pid, true);
|
||||
var res = executeExternalAndWait(cmd, args);
|
||||
var deltaTime = time() - startTime;
|
||||
|
||||
if (res.status === "TERMINATED") {
|
||||
|
|
|
@ -3016,6 +3016,149 @@ static v8::Handle<v8::Value> JS_StatusExternal (v8::Arguments const& argv) {
|
|||
return scope.Close(result);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a external program
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_ExecuteAndWaitExternal (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// extract the arguments
|
||||
if (3 < argv.Length() || argv.Length() < 1) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope,
|
||||
"executeAndWaitExternal(<filename>[, <arguments> [,<usePipes>] ])");
|
||||
}
|
||||
|
||||
TRI_Utf8ValueNFC name(TRI_UNKNOWN_MEM_ZONE, argv[0]);
|
||||
|
||||
if (*name == 0) {
|
||||
TRI_V8_TYPE_ERROR(scope, "<filename> must be a string");
|
||||
}
|
||||
|
||||
char** arguments = 0;
|
||||
uint32_t n = 0;
|
||||
|
||||
if (2 <= argv.Length()) {
|
||||
v8::Handle<v8::Value> a = argv[1];
|
||||
|
||||
if (a->IsArray()) {
|
||||
v8::Handle<v8::Array> arr = v8::Handle<v8::Array>::Cast(a);
|
||||
|
||||
n = arr->Length();
|
||||
arguments = (char**) TRI_Allocate(TRI_CORE_MEM_ZONE, n * sizeof(char*), false);
|
||||
|
||||
for (uint32_t i = 0; i < n; ++i) {
|
||||
TRI_Utf8ValueNFC arg(TRI_UNKNOWN_MEM_ZONE, arr->Get(i));
|
||||
|
||||
if (*arg == 0) {
|
||||
arguments[i] = TRI_DuplicateString("");
|
||||
}
|
||||
else {
|
||||
arguments[i] = TRI_DuplicateString(*arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = 1;
|
||||
arguments = (char**) TRI_Allocate(TRI_CORE_MEM_ZONE, n * sizeof(char*), false);
|
||||
|
||||
TRI_Utf8ValueNFC arg(TRI_UNKNOWN_MEM_ZONE, a);
|
||||
|
||||
if (*arg == 0) {
|
||||
arguments[0] = TRI_DuplicateString("");
|
||||
}
|
||||
else {
|
||||
arguments[0] = TRI_DuplicateString(*arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool usePipes = false;
|
||||
if (3 <= argv.Length()) {
|
||||
usePipes = TRI_ObjectToBoolean(argv[2]);
|
||||
}
|
||||
|
||||
TRI_external_id_t external;
|
||||
TRI_CreateExternalProcess(*name, (const char**) arguments, (size_t) n,
|
||||
usePipes, &external);
|
||||
if (arguments != 0) {
|
||||
for (uint32_t i = 0; i < n; ++i) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, arguments[i]);
|
||||
}
|
||||
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, arguments);
|
||||
}
|
||||
if (external._pid == TRI_INVALID_PROCESS_ID) {
|
||||
TRI_V8_ERROR(scope, "Process could not be started");
|
||||
}
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
result->Set(v8::String::New("pid"), v8::Number::New(external._pid));
|
||||
// Now report about possible stdin and stdout pipes:
|
||||
#ifndef _WIN32
|
||||
if (external._readPipe >= 0) {
|
||||
result->Set(v8::String::New("readPipe"),
|
||||
v8::Number::New(external._readPipe));
|
||||
}
|
||||
if (external._writePipe >= 0) {
|
||||
result->Set(v8::String::New("writePipe"),
|
||||
v8::Number::New(external._writePipe));
|
||||
}
|
||||
#else
|
||||
size_t readPipe_len, writePipe_len;
|
||||
if (0 != external._readPipe) {
|
||||
char* readPipe = TRI_EncodeHexString((const char *)external._readPipe,
|
||||
sizeof(HANDLE), &readPipe_len);
|
||||
result->Set(v8::String::New("readPipe"),
|
||||
v8::String::New(readPipe, (int) readPipe_len));
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, readPipe);
|
||||
}
|
||||
if (0 != external._writePipe) {
|
||||
char* writePipe = TRI_EncodeHexString((const char *)external._writePipe,
|
||||
sizeof(HANDLE), &writePipe_len);
|
||||
result->Set(v8::String::New("writePipe"),
|
||||
v8::String::New(writePipe, (int) writePipe_len));
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, writePipe);
|
||||
}
|
||||
#endif
|
||||
|
||||
TRI_external_id_t pid;
|
||||
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
pid._pid = static_cast<TRI_pid_t>(external._pid);
|
||||
#else
|
||||
pid._pid = static_cast<DWORD>(external._pid);
|
||||
#endif
|
||||
|
||||
TRI_external_status_t external_status = TRI_CheckExternalProcess(pid, true);
|
||||
|
||||
const char* status = "UNKNOWN";
|
||||
|
||||
switch (external_status._status) {
|
||||
case TRI_EXT_NOT_STARTED: status = "NOT-STARTED"; break;
|
||||
case TRI_EXT_PIPE_FAILED: status = "FAILED"; break;
|
||||
case TRI_EXT_FORK_FAILED: status = "FAILED"; break;
|
||||
case TRI_EXT_RUNNING: status = "RUNNING"; break;
|
||||
case TRI_EXT_NOT_FOUND: status = "NOT-FOUND"; break;
|
||||
case TRI_EXT_TERMINATED: status = "TERMINATED"; break;
|
||||
case TRI_EXT_ABORTED: status = "ABORTED"; break;
|
||||
case TRI_EXT_STOPPED: status = "STOPPED"; break;
|
||||
}
|
||||
|
||||
result->Set(v8::String::New("status"), v8::String::New(status));
|
||||
|
||||
if (external_status._status == TRI_EXT_TERMINATED) {
|
||||
result->Set(v8::String::New("exit"), v8::Number::New(external_status._exitStatus));
|
||||
}
|
||||
else if (external_status._status == TRI_EXT_ABORTED) {
|
||||
result->Set(v8::String::New("signal"), v8::Number::New(external_status._exitStatus));
|
||||
}
|
||||
|
||||
// return the result
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief kills an external process
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3633,6 +3776,7 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalFunctionVocbase(context, "SYS_DOWNLOAD", JS_Download);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE_EXTERNAL", JS_ExecuteExternal);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE_EXTERNAL_AND_WAIT", JS_ExecuteAndWaitExternal);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_ALPHA_NUMBERS", JS_RandomAlphaNum);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt);
|
||||
|
|
Loading…
Reference in New Issue