mirror of https://gitee.com/bigwinds/arangodb
Revert "rework process handling (#3322)"
This reverts commit c56e4949b9
.
This commit is contained in:
parent
c56e4949b9
commit
d2b62c99d6
|
@ -765,10 +765,13 @@ function shutdownArangod (arangod, options, forceTerminate) {
|
||||||
if ((arangod.exitStatus === undefined) ||
|
if ((arangod.exitStatus === undefined) ||
|
||||||
(arangod.exitStatus.status === 'RUNNING')) {
|
(arangod.exitStatus.status === 'RUNNING')) {
|
||||||
if (forceTerminate) {
|
if (forceTerminate) {
|
||||||
arangod.exitStatus = killExternal(arangod.pid, abortSignal);
|
killExternal(arangod.pid, abortSignal);
|
||||||
|
arangod.exitStatus = {
|
||||||
|
SIGNAL: String(abortSignal)
|
||||||
|
};
|
||||||
analyzeServerCrash(arangod, options, 'shutdown timeout; instance forcefully KILLED because of fatal timeout in testrun');
|
analyzeServerCrash(arangod, options, 'shutdown timeout; instance forcefully KILLED because of fatal timeout in testrun');
|
||||||
} else if (options.useKillExternal) {
|
} else if (options.useKillExternal) {
|
||||||
arangod.exitStatus = killExternal(arangod.pid);
|
killExternal(arangod.pid);
|
||||||
} else {
|
} else {
|
||||||
const requestOptions = makeAuthorizationHeaders(options);
|
const requestOptions = makeAuthorizationHeaders(options);
|
||||||
requestOptions.method = 'DELETE';
|
requestOptions.method = 'DELETE';
|
||||||
|
@ -861,7 +864,7 @@ function shutdownInstance (instanceInfo, options, forceTerminate) {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
arangod.exitStatus = killExternal(arangod.pid, abortSignal);
|
killExternal(arangod.pid, abortSignal);
|
||||||
analyzeServerCrash(arangod, options, 'shutdown timeout; instance forcefully KILLED after 60s - ' + arangod.exitStatus.signal);
|
analyzeServerCrash(arangod, options, 'shutdown timeout; instance forcefully KILLED after 60s - ' + arangod.exitStatus.signal);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -984,7 +987,7 @@ function startInstanceCluster (instanceInfo, protocol, options,
|
||||||
|
|
||||||
if (!checkArangoAlive(arangod, options)) {
|
if (!checkArangoAlive(arangod, options)) {
|
||||||
instanceInfo.arangods.forEach(arangod => {
|
instanceInfo.arangods.forEach(arangod => {
|
||||||
arangod.exitStatus = killExternal(arangod.pid, abortSignal);
|
killExternal(arangod.pid, abortSignal);
|
||||||
analyzeServerCrash(arangod, options, 'startup timeout; forcefully terminating ' + arangod.role + ' with pid: ' + arangod.pid);
|
analyzeServerCrash(arangod, options, 'startup timeout; forcefully terminating ' + arangod.role + ' with pid: ' + arangod.pid);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1007,7 +1010,7 @@ function startInstanceCluster (instanceInfo, protocol, options,
|
||||||
// Didn't startup in 10 minutes? kill it, give up.
|
// Didn't startup in 10 minutes? kill it, give up.
|
||||||
if (count > 1200) {
|
if (count > 1200) {
|
||||||
instanceInfo.arangods.forEach(arangod => {
|
instanceInfo.arangods.forEach(arangod => {
|
||||||
arangod.exitStatus = killExternal(arangod.pid, abortSignal);
|
killExternal(arangod.pid, abortSignal);
|
||||||
analyzeServerCrash(arangod, options, 'startup timeout; forcefully terminating ' + arangod.role + ' with pid: ' + arangod.pid);
|
analyzeServerCrash(arangod, options, 'startup timeout; forcefully terminating ' + arangod.role + ' with pid: ' + arangod.pid);
|
||||||
});
|
});
|
||||||
throw new Error('cluster startup timed out after 10 minutes!');
|
throw new Error('cluster startup timed out after 10 minutes!');
|
||||||
|
|
|
@ -61,11 +61,100 @@ using namespace arangodb;
|
||||||
|
|
||||||
uint64_t TRI_PhysicalMemory;
|
uint64_t TRI_PhysicalMemory;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief contains all data documented by "proc"
|
||||||
|
///
|
||||||
|
/// @see man 5 proc for the state of a process
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef TRI_HAVE_LINUX_PROC
|
||||||
|
|
||||||
|
typedef struct process_state_s {
|
||||||
|
pid_t pid;
|
||||||
|
/* size was choosen arbitrary */
|
||||||
|
char comm[128];
|
||||||
|
char state;
|
||||||
|
int ppid;
|
||||||
|
int pgrp;
|
||||||
|
int session;
|
||||||
|
int tty_nr;
|
||||||
|
int tpgid;
|
||||||
|
unsigned flags;
|
||||||
|
/* lu */
|
||||||
|
unsigned long minflt;
|
||||||
|
unsigned long cminflt;
|
||||||
|
unsigned long majflt;
|
||||||
|
unsigned long cmajflt;
|
||||||
|
unsigned long utime;
|
||||||
|
unsigned long stime;
|
||||||
|
/* ld */
|
||||||
|
long cutime;
|
||||||
|
long cstime;
|
||||||
|
long priority;
|
||||||
|
long nice;
|
||||||
|
long num_threads;
|
||||||
|
long itrealvalue;
|
||||||
|
/* llu */
|
||||||
|
long long unsigned int starttime;
|
||||||
|
/* lu */
|
||||||
|
unsigned long vsize;
|
||||||
|
/* ld */
|
||||||
|
long rss;
|
||||||
|
/* lu */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long rsslim;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long startcode;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long endcode;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long startstack;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long kstkesp;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long signal;
|
||||||
|
/* obsolete lu*/
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long blocked;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long sigignore;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned int sigcatch;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long wchan;
|
||||||
|
/* no maintained lu */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long nswap;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long cnswap;
|
||||||
|
/* d */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
int exit_signal;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
int processor;
|
||||||
|
/* u */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned rt_priority;
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned policy;
|
||||||
|
/* llu */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
long long unsigned int delayacct_blkio_ticks;
|
||||||
|
/* lu */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
unsigned long guest_time;
|
||||||
|
/* ld */
|
||||||
|
// cppcheck-suppress *
|
||||||
|
long cguest_time;
|
||||||
|
} process_state_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief all external processes
|
/// @brief all external processes
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static std::vector<ExternalProcess*> ExternalProcesses;
|
static std::vector<TRI_external_t*> ExternalProcesses;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief lock for protected access to vector ExternalProcesses
|
/// @brief lock for protected access to vector ExternalProcesses
|
||||||
|
@ -73,84 +162,6 @@ static std::vector<ExternalProcess*> ExternalProcesses;
|
||||||
|
|
||||||
static arangodb::Mutex ExternalProcessesLock;
|
static arangodb::Mutex ExternalProcessesLock;
|
||||||
|
|
||||||
|
|
||||||
ProcessInfo::ProcessInfo():
|
|
||||||
_minorPageFaults(0),
|
|
||||||
_majorPageFaults(0),
|
|
||||||
_userTime(0),
|
|
||||||
_systemTime(0),
|
|
||||||
_numberThreads(0),
|
|
||||||
_residentSize(0), // resident set size in number of bytes
|
|
||||||
_virtualSize(0),
|
|
||||||
_scClkTck(0){}
|
|
||||||
|
|
||||||
ExternalId::ExternalId():
|
|
||||||
#ifndef _WIN32
|
|
||||||
_pid(0),
|
|
||||||
_readPipe(-1),
|
|
||||||
_writePipe(-1) {}
|
|
||||||
#else
|
|
||||||
_pid(0),
|
|
||||||
_readPipe(INVALID_HANDLE_VALUE),
|
|
||||||
_writePipe(INVALID_HANDLE_VALUE) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ExternalProcess::ExternalProcess():
|
|
||||||
_executable(nullptr),
|
|
||||||
_numberArguments(0),
|
|
||||||
_arguments(nullptr),
|
|
||||||
#ifndef _WIN32
|
|
||||||
_pid(0),
|
|
||||||
_readPipe(-1),
|
|
||||||
_writePipe(-1),
|
|
||||||
#else
|
|
||||||
_pid(0),
|
|
||||||
_process(nullptr),
|
|
||||||
_readPipe(INVALID_HANDLE_VALUE),
|
|
||||||
_writePipe(INVALID_HANDLE_VALUE),
|
|
||||||
#endif
|
|
||||||
_status(TRI_EXT_NOT_STARTED),
|
|
||||||
_exitStatus(0) {}
|
|
||||||
|
|
||||||
|
|
||||||
ExternalProcess::~ExternalProcess() {
|
|
||||||
if (_executable != nullptr) {
|
|
||||||
TRI_Free(_executable);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < _numberArguments; i++) {
|
|
||||||
if (_arguments[i] != nullptr) {
|
|
||||||
TRI_Free(_arguments[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_arguments) {
|
|
||||||
TRI_Free(_arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
if (_readPipe != -1) {
|
|
||||||
close(_readPipe);
|
|
||||||
}
|
|
||||||
if (_writePipe != -1) {
|
|
||||||
close(_writePipe);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
CloseHandle(_process);
|
|
||||||
if (_readPipe != INVALID_HANDLE_VALUE) {
|
|
||||||
CloseHandle(_readPipe);
|
|
||||||
}
|
|
||||||
if (_writePipe != INVALID_HANDLE_VALUE) {
|
|
||||||
CloseHandle(_writePipe);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ExternalProcessStatus::ExternalProcessStatus():
|
|
||||||
_status(TRI_EXT_NOT_STARTED),
|
|
||||||
_exitStatus(0),
|
|
||||||
_errorMessage() {}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief creates pipe pair
|
/// @brief creates pipe pair
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -178,7 +189,7 @@ static bool CreatePipes(int* pipe_server_to_child, int* pipe_child_to_server) {
|
||||||
/// @brief starts external process
|
/// @brief starts external process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void StartExternalProcess(ExternalProcess* external, bool usePipes) {
|
static void StartExternalProcess(TRI_external_t* external, bool usePipes) {
|
||||||
int pipe_server_to_child[2];
|
int pipe_server_to_child[2];
|
||||||
int pipe_child_to_server[2];
|
int pipe_child_to_server[2];
|
||||||
|
|
||||||
|
@ -215,6 +226,12 @@ static void StartExternalProcess(ExternalProcess* external, bool usePipes) {
|
||||||
fcntl(2, F_SETFD, 0);
|
fcntl(2, F_SETFD, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore signals in worker process
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
signal(SIGTERM, SIG_IGN);
|
||||||
|
signal(SIGHUP, SIG_IGN);
|
||||||
|
signal(SIGUSR1, SIG_IGN);
|
||||||
|
|
||||||
// execute worker
|
// execute worker
|
||||||
execvp(external->_executable, external->_arguments);
|
execvp(external->_executable, external->_arguments);
|
||||||
|
|
||||||
|
@ -332,7 +349,7 @@ static int appendQuotedArg(TRI_string_buffer_t* buf, char const* p) {
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* makeWindowsArgs(ExternalProcess* external) {
|
static char* makeWindowsArgs(TRI_external_t* external) {
|
||||||
TRI_string_buffer_t* buf;
|
TRI_string_buffer_t* buf;
|
||||||
size_t i;
|
size_t i;
|
||||||
int err = TRI_ERROR_NO_ERROR;
|
int err = TRI_ERROR_NO_ERROR;
|
||||||
|
@ -361,7 +378,7 @@ static char* makeWindowsArgs(ExternalProcess* external) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
|
static bool startProcess(TRI_external_t* external, HANDLE rd, HANDLE wr) {
|
||||||
char* args;
|
char* args;
|
||||||
PROCESS_INFORMATION piProcInfo;
|
PROCESS_INFORMATION piProcInfo;
|
||||||
STARTUPINFO siStartInfo;
|
STARTUPINFO siStartInfo;
|
||||||
|
@ -414,7 +431,7 @@ static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StartExternalProcess(ExternalProcess* external, bool usePipes) {
|
static void StartExternalProcess(TRI_external_t* external, bool usePipes) {
|
||||||
HANDLE hChildStdinRd = NULL, hChildStdinWr = NULL;
|
HANDLE hChildStdinRd = NULL, hChildStdinWr = NULL;
|
||||||
HANDLE hChildStdoutRd = NULL, hChildStdoutWr = NULL;
|
HANDLE hChildStdoutRd = NULL, hChildStdoutWr = NULL;
|
||||||
bool fSuccess;
|
bool fSuccess;
|
||||||
|
@ -459,7 +476,7 @@ static void StartExternalProcess(ExternalProcess* external, bool usePipes) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void TRI_LogProcessInfoSelf(char const* message) {
|
void TRI_LogProcessInfoSelf(char const* message) {
|
||||||
ProcessInfo info = TRI_ProcessInfoSelf();
|
TRI_process_info_t info = TRI_ProcessInfoSelf();
|
||||||
|
|
||||||
if (message == nullptr) {
|
if (message == nullptr) {
|
||||||
message = "";
|
message = "";
|
||||||
|
@ -494,15 +511,16 @@ uint64_t TRI_MicrosecondsTv(struct timeval* tv) {
|
||||||
|
|
||||||
#ifdef TRI_HAVE_LINUX_PROC
|
#ifdef TRI_HAVE_LINUX_PROC
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfoSelf() {
|
TRI_process_info_t TRI_ProcessInfoSelf() {
|
||||||
return TRI_ProcessInfo(Thread::currentProcessId());
|
return TRI_ProcessInfo(Thread::currentProcessId());
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif ARANGODB_HAVE_GETRUSAGE
|
#elif ARANGODB_HAVE_GETRUSAGE
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfoSelf() {
|
TRI_process_info_t TRI_ProcessInfoSelf() {
|
||||||
ProcessInfo result;
|
TRI_process_info_t result;
|
||||||
|
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
result._scClkTck = 1000000;
|
result._scClkTck = 1000000;
|
||||||
|
|
||||||
struct rusage used;
|
struct rusage used;
|
||||||
|
@ -590,9 +608,10 @@ static time_t _FileTime_to_POSIX(FILETIME* ft) {
|
||||||
return (ts - 116444736000000000) / 10000000;
|
return (ts - 116444736000000000) / 10000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfoSelf() {
|
TRI_process_info_t TRI_ProcessInfoSelf() {
|
||||||
ProcessInfo result;
|
TRI_process_info_t result;
|
||||||
PROCESS_MEMORY_COUNTERS_EX pmc;
|
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
|
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
|
||||||
// compiler warning wird in kauf genommen!c
|
// compiler warning wird in kauf genommen!c
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx
|
||||||
|
@ -661,92 +680,9 @@ ProcessInfo TRI_ProcessInfoSelf() {
|
||||||
|
|
||||||
#ifdef TRI_HAVE_LINUX_PROC
|
#ifdef TRI_HAVE_LINUX_PROC
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfo(TRI_pid_t pid) {
|
TRI_process_info_t TRI_ProcessInfo(TRI_pid_t pid) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
TRI_process_info_t result;
|
||||||
/// @brief contains all data documented by "proc"
|
memset(&result, 0, sizeof(result));
|
||||||
///
|
|
||||||
/// @see man 5 proc for the state of a process
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
typedef struct process_state_s {
|
|
||||||
pid_t pid;
|
|
||||||
/* size was choosen arbitrary */
|
|
||||||
char comm[128];
|
|
||||||
char state;
|
|
||||||
int ppid;
|
|
||||||
int pgrp;
|
|
||||||
int session;
|
|
||||||
int tty_nr;
|
|
||||||
int tpgid;
|
|
||||||
unsigned flags;
|
|
||||||
/* lu */
|
|
||||||
unsigned long minflt;
|
|
||||||
unsigned long cminflt;
|
|
||||||
unsigned long majflt;
|
|
||||||
unsigned long cmajflt;
|
|
||||||
unsigned long utime;
|
|
||||||
unsigned long stime;
|
|
||||||
/* ld */
|
|
||||||
long cutime;
|
|
||||||
long cstime;
|
|
||||||
long priority;
|
|
||||||
long nice;
|
|
||||||
long num_threads;
|
|
||||||
long itrealvalue;
|
|
||||||
/* llu */
|
|
||||||
long long unsigned int starttime;
|
|
||||||
/* lu */
|
|
||||||
unsigned long vsize;
|
|
||||||
/* ld */
|
|
||||||
long rss;
|
|
||||||
/* lu */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long rsslim;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long startcode;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long endcode;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long startstack;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long kstkesp;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long signal;
|
|
||||||
/* obsolete lu*/
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long blocked;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long sigignore;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned int sigcatch;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long wchan;
|
|
||||||
/* no maintained lu */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long nswap;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long cnswap;
|
|
||||||
/* d */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
int exit_signal;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
int processor;
|
|
||||||
/* u */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned rt_priority;
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned policy;
|
|
||||||
/* llu */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
long long unsigned int delayacct_blkio_ticks;
|
|
||||||
/* lu */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
unsigned long guest_time;
|
|
||||||
/* ld */
|
|
||||||
// cppcheck-suppress *
|
|
||||||
long cguest_time;
|
|
||||||
} process_state_t;
|
|
||||||
|
|
||||||
ProcessInfo result;
|
|
||||||
|
|
||||||
char fn[1024];
|
char fn[1024];
|
||||||
snprintf(fn, sizeof(fn), "/proc/%d/stat", pid);
|
snprintf(fn, sizeof(fn), "/proc/%d/stat", pid);
|
||||||
|
@ -821,9 +757,10 @@ ProcessInfo TRI_ProcessInfo(TRI_pid_t pid) {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfo(TRI_pid_t pid) {
|
TRI_process_info_t TRI_ProcessInfo(TRI_pid_t pid) {
|
||||||
ProcessInfo result;
|
TRI_process_info_t result;
|
||||||
|
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
result._scClkTck = 1;
|
result._scClkTck = 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -845,21 +782,60 @@ void TRI_SetProcessTitle(char const* title) {
|
||||||
/// @brief frees an external process structure
|
/// @brief frees an external process structure
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void FreeExternal(TRI_external_t* ext) {
|
||||||
|
if (ext == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext->_executable != nullptr) {
|
||||||
|
TRI_Free(ext->_executable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ext->_numberArguments; i++) {
|
||||||
|
if (ext->_arguments[i] != nullptr) {
|
||||||
|
TRI_Free(ext->_arguments[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRI_Free(ext->_arguments);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (ext->_readPipe != -1) {
|
||||||
|
close(ext->_readPipe);
|
||||||
|
}
|
||||||
|
if (ext->_writePipe != -1) {
|
||||||
|
close(ext->_writePipe);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
CloseHandle(ext->_process);
|
||||||
|
if (ext->_readPipe != NULL) {
|
||||||
|
CloseHandle(ext->_readPipe);
|
||||||
|
}
|
||||||
|
if (ext->_writePipe != NULL) {
|
||||||
|
CloseHandle(ext->_writePipe);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
TRI_Free(ext);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief starts an external process
|
/// @brief starts an external process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||||
size_t n, bool usePipes,
|
size_t n, bool usePipes,
|
||||||
ExternalId* pid) {
|
TRI_external_id_t* pid) {
|
||||||
// create the external structure
|
// create the external structure
|
||||||
ExternalProcess* external = new ExternalProcess();
|
TRI_external_t* external = static_cast<TRI_external_t*>(
|
||||||
|
TRI_Allocate(sizeof(TRI_external_t)));
|
||||||
|
|
||||||
if (external == nullptr) {
|
if (external == nullptr) {
|
||||||
// gracefully handle out of memory
|
// gracefully handle out of memory
|
||||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(external, 0, sizeof(TRI_external_t));
|
||||||
|
|
||||||
external->_executable = TRI_DuplicateString(executable);
|
external->_executable = TRI_DuplicateString(executable);
|
||||||
external->_numberArguments = n + 1;
|
external->_numberArguments = n + 1;
|
||||||
|
|
||||||
|
@ -869,7 +845,7 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||||
if (external->_arguments == nullptr) {
|
if (external->_arguments == nullptr) {
|
||||||
// gracefully handle out of memory
|
// gracefully handle out of memory
|
||||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||||
delete external;
|
FreeExternal(external);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,7 +868,7 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||||
|
|
||||||
if (external->_status != TRI_EXT_RUNNING) {
|
if (external->_status != TRI_EXT_RUNNING) {
|
||||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||||
delete external;
|
FreeExternal(external);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,7 +887,7 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||||
ExternalProcesses.push_back(external);
|
ExternalProcesses.push_back(external);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||||
delete external;
|
FreeExternal(external);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -920,13 +896,13 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||||
/// @brief returns the status of an external process
|
/// @brief returns the status of an external process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
TRI_external_status_t TRI_CheckExternalProcess(TRI_external_id_t pid,
|
||||||
bool wait) {
|
bool wait) {
|
||||||
ExternalProcessStatus status;
|
TRI_external_status_t status;
|
||||||
status._status = TRI_EXT_NOT_FOUND;
|
status._status = TRI_EXT_NOT_FOUND;
|
||||||
status._exitStatus = 0;
|
status._exitStatus = 0;
|
||||||
|
|
||||||
ExternalProcess* external = nullptr;
|
TRI_external_t* external = nullptr;
|
||||||
{
|
{
|
||||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
||||||
|
|
||||||
|
@ -985,9 +961,6 @@ ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
||||||
external->_exitStatus = 0;
|
external->_exitStatus = 0;
|
||||||
}
|
}
|
||||||
} else if (res == -1) {
|
} else if (res == -1) {
|
||||||
if (errno == ECHILD) {
|
|
||||||
external->_status = TRI_EXT_NOT_FOUND;
|
|
||||||
}
|
|
||||||
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
||||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "waitpid returned error for pid " << external->_pid << " ("
|
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "waitpid returned error for pid " << external->_pid << " ("
|
||||||
<< wait << "): " << TRI_last_error();
|
<< wait << "): " << TRI_last_error();
|
||||||
|
@ -1124,210 +1097,80 @@ ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete external;
|
FreeExternal(external);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// @brief check for a process we didn't spawn, and check for access rights to
|
|
||||||
// send it signals.
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static ExternalProcess* getExternalProcess(TRI_pid_t pid) {
|
static bool OurKillProcess(TRI_external_t* pid, int signal) {
|
||||||
if (kill(pid, 0) == 0) {
|
if (0 == kill(pid->_pid, signal)) {
|
||||||
ExternalProcess* external = new ExternalProcess();
|
int count;
|
||||||
|
|
||||||
if (external == nullptr) {
|
// Otherwise we just let it be.
|
||||||
// gracefully handle out of memory
|
for (count = 0; count < 10; count++) {
|
||||||
return nullptr;
|
pid_t p;
|
||||||
|
int loc;
|
||||||
|
|
||||||
|
// And wait for it to avoid a zombie:
|
||||||
|
sleep(1);
|
||||||
|
p = waitpid(pid->_pid, &loc, WUNTRACED | WNOHANG);
|
||||||
|
if (p == pid->_pid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (count == 8) {
|
||||||
|
kill(pid->_pid, SIGKILL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
external->_pid = pid;
|
|
||||||
external->_status = TRI_EXT_RUNNING;
|
|
||||||
|
|
||||||
return external;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) <<
|
|
||||||
"checking for external process: '" << pid <<
|
|
||||||
"' failed with error: " << strerror(errno);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static ExternalProcess* getExternalProcess(TRI_pid_t pid) {
|
static bool OurKillProcess(TRI_external_t* pid, int signal) {
|
||||||
|
bool ok = true;
|
||||||
|
UINT uExitCode = 0;
|
||||||
|
DWORD exitCode;
|
||||||
|
|
||||||
|
// kill worker process
|
||||||
|
if (0 != TerminateProcess(pid->_process, uExitCode)) {
|
||||||
|
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "kill of worker process succeeded";
|
||||||
|
} else {
|
||||||
|
DWORD e1 = GetLastError();
|
||||||
|
BOOL ok = GetExitCodeProcess(pid->_process, &exitCode);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "worker process already dead: " << exitCode;
|
||||||
|
} else {
|
||||||
|
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "kill of worker process failed: " << exitCode;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool OurKillProcessPID(DWORD pid) {
|
||||||
HANDLE hProcess;
|
HANDLE hProcess;
|
||||||
|
UINT uExitCode = 0;
|
||||||
|
|
||||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||||
if (hProcess != nullptr) {
|
if (hProcess != nullptr) {
|
||||||
ExternalProcess* external = new ExternalProcess();
|
TerminateProcess(hProcess, uExitCode);
|
||||||
|
CloseHandle(hProcess);
|
||||||
if (external == nullptr) {
|
|
||||||
// gracefully handle out of memory
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
external->_pid = pid;
|
|
||||||
external->_status = TRI_EXT_RUNNING;
|
|
||||||
external->_process = hProcess;
|
|
||||||
|
|
||||||
return external;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// @brief check for a process we didn't spawn, and check for access rights to
|
|
||||||
// send it signals.
|
|
||||||
#ifndef _WIN32
|
|
||||||
static bool killProcess(ExternalProcess* pid, int signal) {
|
|
||||||
if (kill(pid->_pid, signal) == 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
static bool killProcess(ExternalProcess* pid, int signal) {
|
|
||||||
UINT uExitCode = 0;
|
|
||||||
|
|
||||||
// kill worker process
|
|
||||||
if (0 != TerminateProcess(pid->_process, uExitCode)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#define SIGKILL 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
typedef enum e_sig_action {
|
|
||||||
term,
|
|
||||||
core,
|
|
||||||
cont,
|
|
||||||
ign,
|
|
||||||
logrotate,
|
|
||||||
stop,
|
|
||||||
user
|
|
||||||
} e_sig_action;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// @brief find out what impact a signal will have to the process we send it.
|
|
||||||
static e_sig_action whatDoesSignal(int signal) {
|
|
||||||
// Some platforms don't have these. To keep our table clean
|
|
||||||
// we just define them here:
|
|
||||||
#ifndef SIGPOLL
|
|
||||||
#define SIGPOLL 23
|
|
||||||
#endif
|
|
||||||
#ifndef SIGSTKFLT
|
|
||||||
#define SIGSTKFLT 255
|
|
||||||
#endif
|
|
||||||
#ifndef SIGPWR
|
|
||||||
#define SIGPWR 29
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Signal Value Action Comment
|
|
||||||
// ────────────────────────────────────────────────────────────────────
|
|
||||||
switch (signal) {
|
|
||||||
case SIGHUP: // 1 Term Hangup detected on controlling terminal
|
|
||||||
return logrotate; // or death of controlling process
|
|
||||||
// we say this is non-deadly since we should do a logrotate.
|
|
||||||
case SIGINT: // 2 Term Interrupt from keyboard
|
|
||||||
return term;
|
|
||||||
case SIGQUIT: // 3 Core Quit from keyboard
|
|
||||||
case SIGILL: // 4 Core Illegal Instruction
|
|
||||||
case SIGABRT: // 6 Core Abort signal from abort(3)
|
|
||||||
case SIGFPE: // 8 Core Floating-point exception
|
|
||||||
case SIGSEGV: // 11 Core Invalid memory reference
|
|
||||||
return core;
|
|
||||||
case SIGKILL: // 9 Term Kill signal
|
|
||||||
case SIGPIPE: // 13 Term Broken pipe: write to pipe with no
|
|
||||||
// readers; see pipe(7)
|
|
||||||
case SIGALRM: // 14 Term Timer signal from alarm(2)
|
|
||||||
case SIGTERM: // 15 Term Termination signal
|
|
||||||
case SIGUSR1: // 30,10,16 Term User-defined signal 1
|
|
||||||
case SIGUSR2: // 31,12,17 Term User-defined signal 2
|
|
||||||
return term;
|
|
||||||
case SIGCHLD: // 20,17,18 Ign Child stopped or terminated
|
|
||||||
return ign;
|
|
||||||
case SIGCONT: // 19,18,25 Cont Continue if stopped
|
|
||||||
return cont;
|
|
||||||
case SIGSTOP: // 17,19,23 Stop Stop process
|
|
||||||
case SIGTSTP: // 18,20,24 Stop Stop typed at terminal
|
|
||||||
case SIGTTIN: // 21,21,26 Stop Terminal input for background process
|
|
||||||
case SIGTTOU: // 22,22,27 Stop Terminal output for background process
|
|
||||||
return stop;
|
|
||||||
case SIGBUS: // 10,7,10 Core Bus error (bad memory access)
|
|
||||||
return core;
|
|
||||||
case SIGPOLL: // Term Pollable event (Sys V).
|
|
||||||
return term; // Synonym for SIGIO
|
|
||||||
case SIGPROF: // 27,27,29 Term Profiling timer expired
|
|
||||||
return term;
|
|
||||||
case SIGSYS: // 12,31,12 Core Bad system call (SVr4);
|
|
||||||
// see also seccomp(2)
|
|
||||||
case SIGTRAP: // 5 Core Trace/breakpoint trap
|
|
||||||
return core;
|
|
||||||
case SIGURG: // 16,23,21 Ign Urgent condition on socket (4.2BSD)
|
|
||||||
return ign;
|
|
||||||
case SIGVTALRM: // 26,26,28 Term Virtual alarm clock (4.2BSD)
|
|
||||||
return term;
|
|
||||||
case SIGXCPU: // 24,24,30 Core CPU time limit exceeded (4.2BSD);
|
|
||||||
// see setrlimit(2)
|
|
||||||
case SIGXFSZ: // 25,25,31 Core File size limit exceeded (4.2BSD);
|
|
||||||
// see setrlimit(2)
|
|
||||||
//case SIGIOT: // 6 Core IOT trap. A synonym for SIGABRT
|
|
||||||
return core;
|
|
||||||
//case SIGEMT: // 7,-,7 Term Emulator trap
|
|
||||||
case SIGSTKFLT: // -,16,- Term Stack fault on coprocessor (unused)
|
|
||||||
//case SIGIO: // 23,29,22 Term I/O now possible (4.2BSD)
|
|
||||||
case SIGPWR: // 29,30,19 Term Power failure (System V)
|
|
||||||
//case SIGINFO: // 29,-,- A synonym for SIGPWR
|
|
||||||
//case SIGLOST: // -,-,- Term File lock lost (unused)
|
|
||||||
return term;
|
|
||||||
//case SIGCLD: // -,-,18 Ign A synonym for SIGCHLD
|
|
||||||
case SIGWINCH: // 28,28,20 Ign Window resize signal (4.3BSD, Sun)
|
|
||||||
return ign;
|
|
||||||
//case SIGUNUSED: // -,31,- Core Synonymous with SIGSYS
|
|
||||||
// return core;
|
|
||||||
default:
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
return term;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool TRI_IsDeadlySignal(int signal) {
|
|
||||||
#ifndef _WIN32
|
|
||||||
switch (whatDoesSignal(signal)) {
|
|
||||||
case term:
|
|
||||||
return true;
|
|
||||||
case core:
|
|
||||||
return true;
|
|
||||||
case cont:
|
|
||||||
return false;
|
|
||||||
case ign:
|
|
||||||
return false;
|
|
||||||
case logrotate:
|
|
||||||
return false;
|
|
||||||
case stop:
|
|
||||||
return false;
|
|
||||||
case user: // user signals aren't supposed to be deadly.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// well windows... always deadly.
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief kills an external process
|
/// @brief kills an external process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExternalProcessStatus TRI_KillExternalProcess(ExternalId pid, int signal, bool isTerminal) {
|
bool TRI_KillExternalProcess(TRI_external_id_t pid, int signal) {
|
||||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "Sending process: " << pid._pid << " the signal: " << signal;
|
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "killing process: " << pid._pid;
|
||||||
|
|
||||||
ExternalProcess* external = nullptr; // just to please the compiler
|
TRI_external_t* external = nullptr; // just to please the compiler
|
||||||
{
|
{
|
||||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
||||||
|
|
||||||
|
@ -1335,86 +1178,55 @@ ExternalProcessStatus TRI_KillExternalProcess(ExternalId pid, int signal, bool i
|
||||||
++it) {
|
++it) {
|
||||||
if ((*it)->_pid == pid._pid) {
|
if ((*it)->_pid == pid._pid) {
|
||||||
external = (*it);
|
external = (*it);
|
||||||
|
ExternalProcesses.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isChild = (external != nullptr);
|
if (external == nullptr) {
|
||||||
if (!isChild) {
|
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "kill: process not found: " << pid._pid;
|
||||||
external = getExternalProcess(pid._pid);
|
#ifndef _WIN32
|
||||||
if (external == nullptr) {
|
// Kill just in case:
|
||||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "kill: process not found: " << pid._pid << " in our starting table and it doesn't exist.";
|
if (0 == kill(pid._pid, signal)) {
|
||||||
ExternalProcessStatus status;
|
// Otherwise we just let it be.
|
||||||
status._status = TRI_EXT_NOT_FOUND;
|
for (int count = 0; count < 10; count++) {
|
||||||
status._exitStatus = -1;
|
int loc;
|
||||||
return status;
|
pid_t p;
|
||||||
}
|
|
||||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "kill: process not found: " << pid._pid << " in our starting table - adding";
|
|
||||||
|
|
||||||
// ok, we didn't spawn it, but now we claim the
|
// And wait for it to avoid a zombie:
|
||||||
// ownership.
|
sleep(1);
|
||||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
p = waitpid(pid._pid, &loc, WUNTRACED | WNOHANG);
|
||||||
|
if (p == pid._pid) {
|
||||||
try {
|
return true;
|
||||||
ExternalProcesses.push_back(external);
|
|
||||||
} catch (...) {
|
|
||||||
ExternalProcessStatus status;
|
|
||||||
delete external;
|
|
||||||
|
|
||||||
status._status = TRI_EXT_NOT_FOUND;
|
|
||||||
status._exitStatus = -1;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (killProcess(external, signal)) {
|
|
||||||
external->_status = TRI_EXT_STOPPED;
|
|
||||||
// if the process wasn't spawned by us, no waiting required.
|
|
||||||
int count = 0;
|
|
||||||
while (true) {
|
|
||||||
ExternalProcessStatus status = TRI_CheckExternalProcess(pid, false);
|
|
||||||
if (! isTerminal) {
|
|
||||||
// we just sent a signal, don't care whether
|
|
||||||
// the process is gone by now.
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
if ((status._status == TRI_EXT_TERMINATED) ||
|
|
||||||
(status._status == TRI_EXT_ABORTED) ||
|
|
||||||
(status._status == TRI_EXT_NOT_FOUND)) {
|
|
||||||
// Its dead and gone - good.
|
|
||||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
|
||||||
for (auto it = ExternalProcesses.begin(); it != ExternalProcesses.end();
|
|
||||||
++it) {
|
|
||||||
if (*it == external) {
|
|
||||||
ExternalProcesses.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!isChild && (status._status == TRI_EXT_NOT_FOUND) ) {
|
if (count == 8) {
|
||||||
status._status = TRI_EXT_TERMINATED;
|
kill(pid._pid, SIGKILL);
|
||||||
status._errorMessage.clear();
|
|
||||||
}
|
}
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
sleep(1);
|
|
||||||
if (count >= 8) {
|
|
||||||
killProcess(external, SIGKILL);
|
|
||||||
}
|
|
||||||
if (count > 20) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
count ++;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return OurKillProcessPID(pid._pid);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return TRI_CheckExternalProcess(pid, false);
|
|
||||||
|
bool ok = true;
|
||||||
|
if (external->_status == TRI_EXT_RUNNING ||
|
||||||
|
external->_status == TRI_EXT_STOPPED) {
|
||||||
|
ok = OurKillProcess(external, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeExternal(external);
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief stops an external process, only on Unix
|
/// @brief stops an external process, only on Unix
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool TRI_SuspendExternalProcess(ExternalId pid) {
|
bool TRI_SuspendExternalProcess(TRI_external_id_t pid) {
|
||||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "suspending process: " << pid._pid;
|
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "suspending process: " << pid._pid;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -1428,7 +1240,7 @@ bool TRI_SuspendExternalProcess(ExternalId pid) {
|
||||||
/// @brief continues an external process, only on Unix
|
/// @brief continues an external process, only on Unix
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool TRI_ContinueExternalProcess(ExternalId pid) {
|
bool TRI_ContinueExternalProcess(TRI_external_id_t pid) {
|
||||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "continueing process: " << pid._pid;
|
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "continueing process: " << pid._pid;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -1483,7 +1295,19 @@ static uint64_t GetPhysicalMemory() {
|
||||||
return (uint64_t)status.ullTotalPhys;
|
return (uint64_t)status.ullTotalPhys;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TRI_HAVE_WIN32_GLOBAL_MEMORY_STATUS
|
#else
|
||||||
|
|
||||||
|
static uint64_t GetPhysicalMemory() {
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
|
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx
|
||||||
|
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, pmc.cb)) {
|
||||||
|
return pmc.PeakWorkingSetSize;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1501,8 +1325,8 @@ void TRI_InitializeProcess() {
|
||||||
|
|
||||||
void TRI_ShutdownProcess() {
|
void TRI_ShutdownProcess() {
|
||||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
||||||
for (auto* external : ExternalProcesses) {
|
for (auto* e : ExternalProcesses) {
|
||||||
delete external;
|
FreeExternal(e);
|
||||||
}
|
}
|
||||||
ExternalProcesses.clear();
|
ExternalProcesses.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ extern uint64_t TRI_PhysicalMemory;
|
||||||
/// @brief returns information about the process
|
/// @brief returns information about the process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ProcessInfo {
|
typedef struct TRI_process_info_s {
|
||||||
uint64_t _minorPageFaults;
|
uint64_t _minorPageFaults;
|
||||||
uint64_t _majorPageFaults;
|
uint64_t _majorPageFaults;
|
||||||
uint64_t _userTime;
|
uint64_t _userTime;
|
||||||
|
@ -56,9 +56,7 @@ struct ProcessInfo {
|
||||||
int64_t _residentSize; // resident set size in number of bytes
|
int64_t _residentSize; // resident set size in number of bytes
|
||||||
uint64_t _virtualSize;
|
uint64_t _virtualSize;
|
||||||
uint64_t _scClkTck;
|
uint64_t _scClkTck;
|
||||||
|
} TRI_process_info_t;
|
||||||
ProcessInfo();
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief status of an external process
|
/// @brief status of an external process
|
||||||
|
@ -80,27 +78,24 @@ typedef enum {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
struct ExternalId {
|
typedef struct TRI_external_id_s {
|
||||||
TRI_pid_t _pid;
|
TRI_pid_t _pid;
|
||||||
int _readPipe;
|
int _readPipe;
|
||||||
int _writePipe;
|
int _writePipe;
|
||||||
ExternalId();
|
} TRI_external_id_t;
|
||||||
};
|
|
||||||
#else
|
#else
|
||||||
struct ExternalId {
|
typedef struct TRI_external_id_s {
|
||||||
DWORD _pid;
|
DWORD _pid;
|
||||||
HANDLE _readPipe;
|
HANDLE _readPipe;
|
||||||
HANDLE _writePipe;
|
HANDLE _writePipe;
|
||||||
|
} TRI_external_id_t;
|
||||||
ExternalId();
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief external process description
|
/// @brief external process description
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ExternalProcess {
|
struct TRI_external_t {
|
||||||
char* _executable;
|
char* _executable;
|
||||||
size_t _numberArguments;
|
size_t _numberArguments;
|
||||||
char** _arguments;
|
char** _arguments;
|
||||||
|
@ -118,21 +113,16 @@ struct ExternalProcess {
|
||||||
|
|
||||||
TRI_external_status_e _status;
|
TRI_external_status_e _status;
|
||||||
int64_t _exitStatus;
|
int64_t _exitStatus;
|
||||||
|
|
||||||
~ExternalProcess();
|
|
||||||
ExternalProcess();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief external process status
|
/// @brief external process status
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ExternalProcessStatus {
|
struct TRI_external_status_t {
|
||||||
TRI_external_status_e _status;
|
TRI_external_status_e _status;
|
||||||
int64_t _exitStatus;
|
int64_t _exitStatus;
|
||||||
std::string _errorMessage;
|
std::string _errorMessage;
|
||||||
|
|
||||||
ExternalProcessStatus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void TRI_LogProcessInfoSelf(char const* message = nullptr);
|
void TRI_LogProcessInfoSelf(char const* message = nullptr);
|
||||||
|
@ -149,13 +139,13 @@ uint64_t TRI_MicrosecondsTv(struct timeval* tv);
|
||||||
/// @brief returns information about the current process
|
/// @brief returns information about the current process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfoSelf(void);
|
TRI_process_info_t TRI_ProcessInfoSelf(void);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns information about the process
|
/// @brief returns information about the process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ProcessInfo TRI_ProcessInfo(TRI_pid_t pid);
|
TRI_process_info_t TRI_ProcessInfo(TRI_pid_t pid);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief sets the process name
|
/// @brief sets the process name
|
||||||
|
@ -168,39 +158,32 @@ void TRI_SetProcessTitle(char const* title);
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||||
size_t n, bool usePipes, ExternalId* pid);
|
size_t n, bool usePipes, TRI_external_id_t* pid);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns the status of an external process
|
/// @brief returns the status of an external process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
TRI_external_status_t TRI_CheckExternalProcess(TRI_external_id_t pid,
|
||||||
bool wait);
|
bool wait);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief whether a signal is expected to be terminal
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
bool TRI_IsDeadlySignal(int signal);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief kills an external process
|
/// @brief kills an external process
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExternalProcessStatus TRI_KillExternalProcess(ExternalId pid,
|
bool TRI_KillExternalProcess(TRI_external_id_t pid, int signal);
|
||||||
int signal,
|
|
||||||
bool isTerminal);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief suspends an external process, only on Unix
|
/// @brief suspends an external process, only on Unix
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool TRI_SuspendExternalProcess(ExternalId pid);
|
bool TRI_SuspendExternalProcess(TRI_external_id_t pid);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief continue an external process, only on Unix
|
/// @brief continue an external process, only on Unix
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool TRI_ContinueExternalProcess(ExternalId pid);
|
bool TRI_ContinueExternalProcess(TRI_external_id_t pid);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief initializes the process components
|
/// @brief initializes the process components
|
||||||
|
|
|
@ -721,17 +721,3 @@ bool terminalKnowsANSIColors()
|
||||||
// Windows 8 onwards the CMD window understands ANSI-Colorcodes.
|
// Windows 8 onwards the CMD window understands ANSI-Colorcodes.
|
||||||
return IsWindows8OrGreater();
|
return IsWindows8OrGreater();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <atlstr.h>
|
|
||||||
std::string getFileNameFromHandle(HANDLE fileHandle) {
|
|
||||||
char buff[sizeof(FILE_NAME_INFO) + sizeof(WCHAR)*MAX_PATH];
|
|
||||||
FILE_NAME_INFO *FileInformation = (FILE_NAME_INFO*) buff;
|
|
||||||
|
|
||||||
if (!GetFileInformationByHandleEx(fileHandle,
|
|
||||||
FileNameInfo,
|
|
||||||
FileInformation, sizeof(buff)
|
|
||||||
)) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
return std::string((LPCTSTR)CString(FileInformation->FileName));
|
|
||||||
}
|
|
||||||
|
|
|
@ -151,9 +151,5 @@ int _is_cyg_tty(int fd);
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool terminalKnowsANSIColors();
|
bool terminalKnowsANSIColors();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// returns returns the filename in conjunction with a handle
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
std::string getFileNameFromHandle(HANDLE fileHandle);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2367,7 +2367,7 @@ static void JS_ProcessStatistics(
|
||||||
|
|
||||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||||
|
|
||||||
ProcessInfo info = TRI_ProcessInfoSelf();
|
TRI_process_info_t info = TRI_ProcessInfoSelf();
|
||||||
double rss = (double)info._residentSize;
|
double rss = (double)info._residentSize;
|
||||||
double rssp = 0;
|
double rssp = 0;
|
||||||
|
|
||||||
|
@ -3384,106 +3384,6 @@ static void JS_HMAC(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief Convert programm stati to V8
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
static char const* convertProcessStatusToString(ExternalProcessStatus external) {
|
|
||||||
char const* status = "UNKNOWN";
|
|
||||||
|
|
||||||
switch (external._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;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void convertPipeStatus(v8::FunctionCallbackInfo<v8::Value> const& args,
|
|
||||||
v8::Handle<v8::Object> &result,
|
|
||||||
ExternalId &external) {
|
|
||||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
|
||||||
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "pid"),
|
|
||||||
v8::Number::New(isolate, external._pid));
|
|
||||||
|
|
||||||
// Now report about possible stdin and stdout pipes:
|
|
||||||
#ifndef _WIN32
|
|
||||||
if (external._readPipe >= 0) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "readPipe"),
|
|
||||||
v8::Number::New(isolate, external._readPipe));
|
|
||||||
}
|
|
||||||
if (external._writePipe >= 0) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "writePipe"),
|
|
||||||
v8::Number::New(isolate, external._writePipe));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (external._readPipe != INVALID_HANDLE_VALUE) {
|
|
||||||
auto fn = getFileNameFromHandle(external._readPipe);
|
|
||||||
if (fn.length() > 0) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "readPipe"),
|
|
||||||
TRI_V8_STD_STRING(isolate, fn));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (external._writePipe != INVALID_HANDLE_VALUE) {
|
|
||||||
auto fn = getFileNameFromHandle(external._writePipe);
|
|
||||||
if (fn.length() > 0) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "writePipe"),
|
|
||||||
TRI_V8_STD_STRING(isolate, fn));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
TRI_V8_TRY_CATCH_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void convertStatusToV8(v8::FunctionCallbackInfo<v8::Value> const& args,
|
|
||||||
v8::Handle<v8::Object> &result,
|
|
||||||
ExternalProcessStatus &external_status,
|
|
||||||
ExternalId &external) {
|
|
||||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
|
||||||
|
|
||||||
convertPipeStatus(args, result, external);
|
|
||||||
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "status"),
|
|
||||||
TRI_V8_ASCII_STRING(isolate, convertProcessStatusToString(external_status)));
|
|
||||||
|
|
||||||
if (external_status._status == TRI_EXT_TERMINATED) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "exit"),
|
|
||||||
v8::Integer::New(isolate, static_cast<int32_t>(
|
|
||||||
external_status._exitStatus)));
|
|
||||||
} else if (external_status._status == TRI_EXT_ABORTED) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "signal"),
|
|
||||||
v8::Integer::New(isolate, static_cast<int32_t>(
|
|
||||||
external_status._exitStatus)));
|
|
||||||
}
|
|
||||||
if (external_status._errorMessage.length() > 0) {
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "errorMessage"),
|
|
||||||
TRI_V8_STD_STRING(isolate, external_status._errorMessage));
|
|
||||||
}
|
|
||||||
TRI_V8_TRY_CATCH_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief executes a external program
|
/// @brief executes a external program
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -3554,7 +3454,7 @@ static void JS_ExecuteExternal(
|
||||||
usePipes = TRI_ObjectToBoolean(args[2]);
|
usePipes = TRI_ObjectToBoolean(args[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalId external;
|
TRI_external_id_t external;
|
||||||
TRI_CreateExternalProcess(*name, const_cast<char const**>(arguments),
|
TRI_CreateExternalProcess(*name, const_cast<char const**>(arguments),
|
||||||
(size_t)n, usePipes, &external);
|
(size_t)n, usePipes, &external);
|
||||||
if (arguments != nullptr) {
|
if (arguments != nullptr) {
|
||||||
|
@ -3570,9 +3470,39 @@ static void JS_ExecuteExternal(
|
||||||
TRI_V8_THROW_ERROR("Process could not be started");
|
TRI_V8_THROW_ERROR("Process could not be started");
|
||||||
}
|
}
|
||||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "pid"),
|
||||||
convertPipeStatus(args, result, external);
|
v8::Number::New(isolate, external._pid));
|
||||||
|
// Now report about possible stdin and stdout pipes:
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (external._readPipe >= 0) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "readPipe"),
|
||||||
|
v8::Number::New(isolate, external._readPipe));
|
||||||
|
}
|
||||||
|
if (external._writePipe >= 0) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "writePipe"),
|
||||||
|
v8::Number::New(isolate, external._writePipe));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_t readPipe_len, writePipe_len;
|
||||||
|
if (0 != external._readPipe) {
|
||||||
|
char* readPipe = TRI_EncodeHexString((char const*)external._readPipe,
|
||||||
|
sizeof(HANDLE), &readPipe_len);
|
||||||
|
if (readPipe != nullptr) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "readPipe"),
|
||||||
|
TRI_V8_PAIR_STRING(isolate, readPipe, (int)readPipe_len));
|
||||||
|
TRI_FreeString(readPipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 != external._writePipe) {
|
||||||
|
char* writePipe = TRI_EncodeHexString((char const*)external._writePipe,
|
||||||
|
sizeof(HANDLE), &writePipe_len);
|
||||||
|
if (writePipe != nullptr) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "writePipe"),
|
||||||
|
TRI_V8_PAIR_STRING(isolate, writePipe, (int)writePipe_len));
|
||||||
|
TRI_FreeString(writePipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
TRI_V8_RETURN(result);
|
TRI_V8_RETURN(result);
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
@ -3591,7 +3521,8 @@ static void JS_StatusExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
"statusExternal(<external-identifier>[, <wait>])");
|
"statusExternal(<external-identifier>[, <wait>])");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalId pid;
|
TRI_external_id_t pid;
|
||||||
|
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
||||||
|
@ -3603,12 +3534,39 @@ static void JS_StatusExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
wait = TRI_ObjectToBoolean(args[1]);
|
wait = TRI_ObjectToBoolean(args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalProcessStatus external = TRI_CheckExternalProcess(pid, wait);
|
TRI_external_status_t external = TRI_CheckExternalProcess(pid, wait);
|
||||||
|
|
||||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||||
|
char const* status = "UNKNOWN";
|
||||||
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "status"),
|
switch (external._status) {
|
||||||
TRI_V8_STRING(isolate, convertProcessStatusToString(external)));
|
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(TRI_V8_ASCII_STRING(isolate, "status"), TRI_V8_STRING(isolate, status));
|
||||||
|
|
||||||
if (external._status == TRI_EXT_TERMINATED) {
|
if (external._status == TRI_EXT_TERMINATED) {
|
||||||
result->Set(
|
result->Set(
|
||||||
|
@ -3627,6 +3585,7 @@ static void JS_StatusExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
TRI_V8_RETURN(result);
|
TRI_V8_RETURN(result);
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief executes a external program
|
/// @brief executes a external program
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -3693,7 +3652,7 @@ static void JS_ExecuteAndWaitExternal(
|
||||||
usePipes = TRI_ObjectToBoolean(args[2]);
|
usePipes = TRI_ObjectToBoolean(args[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalId external;
|
TRI_external_id_t external;
|
||||||
TRI_CreateExternalProcess(*name, const_cast<char const**>(arguments),
|
TRI_CreateExternalProcess(*name, const_cast<char const**>(arguments),
|
||||||
static_cast<size_t>(n), usePipes, &external);
|
static_cast<size_t>(n), usePipes, &external);
|
||||||
if (arguments != nullptr) {
|
if (arguments != nullptr) {
|
||||||
|
@ -3709,15 +3668,91 @@ static void JS_ExecuteAndWaitExternal(
|
||||||
TRI_V8_THROW_ERROR("Process could not be started");
|
TRI_V8_THROW_ERROR("Process could not be started");
|
||||||
}
|
}
|
||||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "pid"),
|
||||||
|
v8::Number::New(isolate, external._pid));
|
||||||
|
// Now report about possible stdin and stdout pipes:
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (external._readPipe >= 0) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "readPipe"),
|
||||||
|
v8::Number::New(isolate, external._readPipe));
|
||||||
|
}
|
||||||
|
if (external._writePipe >= 0) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "writePipe"),
|
||||||
|
v8::Number::New(isolate, external._writePipe));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_t readPipe_len, writePipe_len;
|
||||||
|
if (0 != external._readPipe) {
|
||||||
|
char* readPipe = TRI_EncodeHexString((char const*)external._readPipe,
|
||||||
|
sizeof(HANDLE), &readPipe_len);
|
||||||
|
if (readPipe != nullptr) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "readPipe"),
|
||||||
|
TRI_V8_PAIR_STRING(isolate, readPipe, (int)readPipe_len));
|
||||||
|
TRI_FreeString(readPipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 != external._writePipe) {
|
||||||
|
char* writePipe = TRI_EncodeHexString((char const*)external._writePipe,
|
||||||
|
sizeof(HANDLE), &writePipe_len);
|
||||||
|
if (writePipe != nullptr) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "writePipe"),
|
||||||
|
TRI_V8_PAIR_STRING(isolate, writePipe, (int)writePipe_len));
|
||||||
|
TRI_FreeString(writePipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ExternalId pid;
|
TRI_external_id_t pid;
|
||||||
|
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||||
|
|
||||||
pid._pid = external._pid;
|
pid._pid = external._pid;
|
||||||
|
|
||||||
auto external_status = TRI_CheckExternalProcess(pid, true);
|
TRI_external_status_t external_status = TRI_CheckExternalProcess(pid, true);
|
||||||
|
|
||||||
convertStatusToV8(args, result, external_status, external);
|
char const* 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(TRI_V8_ASCII_STRING(isolate, "status"), TRI_V8_ASCII_STRING(isolate, status));
|
||||||
|
|
||||||
|
if (external_status._status == TRI_EXT_TERMINATED) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "exit"),
|
||||||
|
v8::Integer::New(isolate, static_cast<int32_t>(
|
||||||
|
external_status._exitStatus)));
|
||||||
|
} else if (external_status._status == TRI_EXT_ABORTED) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "signal"),
|
||||||
|
v8::Integer::New(isolate, static_cast<int32_t>(
|
||||||
|
external_status._exitStatus)));
|
||||||
|
}
|
||||||
|
if (external_status._errorMessage.length() > 0) {
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "errorMessage"),
|
||||||
|
TRI_V8_STD_STRING(isolate, external_status._errorMessage));
|
||||||
|
}
|
||||||
// return the result
|
// return the result
|
||||||
TRI_V8_RETURN(result);
|
TRI_V8_RETURN(result);
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
|
@ -3734,22 +3769,14 @@ static void JS_KillExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
// extract the arguments
|
// extract the arguments
|
||||||
if (args.Length() < 1 || args.Length() > 2) {
|
if (args.Length() < 1 || args.Length() > 2) {
|
||||||
TRI_V8_THROW_EXCEPTION_USAGE(
|
TRI_V8_THROW_EXCEPTION_USAGE(
|
||||||
"killExternal(<external-identifier>[[, <signal>], isTerminal])");
|
"killExternal(<external-identifier>, <signal>)");
|
||||||
}
|
}
|
||||||
int signal = SIGTERM;
|
int signal = SIGTERM;
|
||||||
if (args.Length() >= 2) {
|
if (args.Length() == 2) {
|
||||||
signal = static_cast<int>(TRI_ObjectToInt64(args[1]));
|
signal = static_cast<int>(TRI_ObjectToInt64(args[1]));
|
||||||
}
|
}
|
||||||
|
TRI_external_id_t pid;
|
||||||
bool isTerminating;
|
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||||
if (args.Length() >= 3) {
|
|
||||||
isTerminating = TRI_ObjectToBoolean(args[2]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isTerminating = TRI_IsDeadlySignal(signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExternalId pid;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
||||||
|
@ -3758,16 +3785,10 @@ static void JS_KillExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// return the result
|
// return the result
|
||||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
if (TRI_KillExternalProcess(pid, signal)) {
|
||||||
ExternalId external;
|
TRI_V8_RETURN_TRUE();
|
||||||
external._pid = pid._pid;
|
}
|
||||||
|
TRI_V8_RETURN_FALSE();
|
||||||
auto external_status = TRI_KillExternalProcess(pid, signal, isTerminating);
|
|
||||||
|
|
||||||
convertStatusToV8(args, result, external_status, external);
|
|
||||||
|
|
||||||
// return the result
|
|
||||||
TRI_V8_RETURN(result);
|
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3785,7 +3806,8 @@ static void JS_SuspendExternal(
|
||||||
TRI_V8_THROW_EXCEPTION_USAGE("suspendExternal(<external-identifier>)");
|
TRI_V8_THROW_EXCEPTION_USAGE("suspendExternal(<external-identifier>)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalId pid;
|
TRI_external_id_t pid;
|
||||||
|
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
||||||
|
@ -3815,7 +3837,8 @@ static void JS_ContinueExternal(
|
||||||
TRI_V8_THROW_EXCEPTION_USAGE("continueExternal(<external-identifier>)");
|
TRI_V8_THROW_EXCEPTION_USAGE("continueExternal(<external-identifier>)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalId pid;
|
TRI_external_id_t pid;
|
||||||
|
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
||||||
|
|
Loading…
Reference in New Issue