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,
|
COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION,
|
||||||
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
|
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
|
||||||
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
|
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
|
||||||
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL,
|
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_EXECUTE_EXTERNAL_AND_WAIT,
|
||||||
SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT, SYS_IS_IP */
|
SYS_KILL_EXTERNAL, SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT,
|
||||||
|
SYS_IS_IP */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief module "internal"
|
/// @brief module "internal"
|
||||||
|
@ -689,6 +690,20 @@
|
||||||
delete SYS_EXECUTE_EXTERNAL;
|
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
|
/// @brief killExternal
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -17,8 +17,9 @@
|
||||||
COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION,
|
COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION,
|
||||||
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
|
BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION,
|
||||||
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
|
REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH,
|
||||||
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL,
|
SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_EXECUTE_EXTERNAL_AND_WAIT,
|
||||||
SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT, SYS_IS_IP */
|
SYS_KILL_EXTERNAL, SYS_REGISTER_TASK, SYS_UNREGISTER_TASK, SYS_GET_TASK, SYS_TEST_PORT,
|
||||||
|
SYS_IS_IP */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief module "internal"
|
/// @brief module "internal"
|
||||||
|
@ -689,6 +690,15 @@
|
||||||
delete SYS_EXECUTE_EXTERNAL;
|
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
|
/// @brief killExternal
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -93,6 +93,7 @@ var wait = require("internal").wait;
|
||||||
var executeExternal = require("internal").executeExternal;
|
var executeExternal = require("internal").executeExternal;
|
||||||
var killExternal = require("internal").killExternal;
|
var killExternal = require("internal").killExternal;
|
||||||
var statusExternal = require("internal").statusExternal;
|
var statusExternal = require("internal").statusExternal;
|
||||||
|
var executeExternalAndWait = require("internal").executeExternalAndWait;
|
||||||
var base64Encode = require("internal").base64Encode;
|
var base64Encode = require("internal").base64Encode;
|
||||||
|
|
||||||
var PortFinder = require("org/arangodb/cluster").PortFinder;
|
var PortFinder = require("org/arangodb/cluster").PortFinder;
|
||||||
|
@ -398,9 +399,8 @@ function runThere (options, instanceInfo, file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeAndWait (cmd, args) {
|
function executeAndWait (cmd, args) {
|
||||||
var pid = executeExternal(cmd, args);
|
|
||||||
var startTime = time();
|
var startTime = time();
|
||||||
var res = statusExternal(pid, true);
|
var res = executeExternalAndWait(cmd, args);
|
||||||
var deltaTime = time() - startTime;
|
var deltaTime = time() - startTime;
|
||||||
|
|
||||||
if (res.status === "TERMINATED") {
|
if (res.status === "TERMINATED") {
|
||||||
|
|
|
@ -3016,6 +3016,149 @@ static v8::Handle<v8::Value> JS_StatusExternal (v8::Arguments const& argv) {
|
||||||
return scope.Close(result);
|
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
|
/// @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_DOWNLOAD", JS_Download);
|
||||||
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute);
|
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute);
|
||||||
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE_EXTERNAL", JS_ExecuteExternal);
|
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_ALPHA_NUMBERS", JS_RandomAlphaNum);
|
||||||
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers);
|
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers);
|
||||||
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt);
|
TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt);
|
||||||
|
|
Loading…
Reference in New Issue