1
0
Fork 0

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:
Willi Goesgens 2014-10-08 16:48:30 +02:00
parent cd2e386a19
commit e433a2831e
4 changed files with 175 additions and 6 deletions

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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") {

View File

@ -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);