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) ||
|
||||
(arangod.exitStatus.status === 'RUNNING')) {
|
||||
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');
|
||||
} else if (options.useKillExternal) {
|
||||
arangod.exitStatus = killExternal(arangod.pid);
|
||||
killExternal(arangod.pid);
|
||||
} else {
|
||||
const requestOptions = makeAuthorizationHeaders(options);
|
||||
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);
|
||||
return false;
|
||||
} else {
|
||||
|
@ -984,7 +987,7 @@ function startInstanceCluster (instanceInfo, protocol, options,
|
|||
|
||||
if (!checkArangoAlive(arangod, options)) {
|
||||
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);
|
||||
});
|
||||
|
||||
|
@ -1007,7 +1010,7 @@ function startInstanceCluster (instanceInfo, protocol, options,
|
|||
// Didn't startup in 10 minutes? kill it, give up.
|
||||
if (count > 1200) {
|
||||
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);
|
||||
});
|
||||
throw new Error('cluster startup timed out after 10 minutes!');
|
||||
|
|
|
@ -61,11 +61,100 @@ using namespace arangodb;
|
|||
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::vector<ExternalProcess*> ExternalProcesses;
|
||||
static std::vector<TRI_external_t*> ExternalProcesses;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lock for protected access to vector ExternalProcesses
|
||||
|
@ -73,84 +162,6 @@ static std::vector<ExternalProcess*> ExternalProcesses;
|
|||
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -178,7 +189,7 @@ static bool CreatePipes(int* pipe_server_to_child, int* pipe_child_to_server) {
|
|||
/// @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_child_to_server[2];
|
||||
|
||||
|
@ -215,6 +226,12 @@ static void StartExternalProcess(ExternalProcess* external, bool usePipes) {
|
|||
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
|
||||
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;
|
||||
}
|
||||
|
||||
static char* makeWindowsArgs(ExternalProcess* external) {
|
||||
static char* makeWindowsArgs(TRI_external_t* external) {
|
||||
TRI_string_buffer_t* buf;
|
||||
size_t i;
|
||||
int err = TRI_ERROR_NO_ERROR;
|
||||
|
@ -361,7 +378,7 @@ static char* makeWindowsArgs(ExternalProcess* external) {
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
|
||||
static bool startProcess(TRI_external_t* external, HANDLE rd, HANDLE wr) {
|
||||
char* args;
|
||||
PROCESS_INFORMATION piProcInfo;
|
||||
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 hChildStdoutRd = NULL, hChildStdoutWr = NULL;
|
||||
bool fSuccess;
|
||||
|
@ -459,7 +476,7 @@ static void StartExternalProcess(ExternalProcess* external, bool usePipes) {
|
|||
#endif
|
||||
|
||||
void TRI_LogProcessInfoSelf(char const* message) {
|
||||
ProcessInfo info = TRI_ProcessInfoSelf();
|
||||
TRI_process_info_t info = TRI_ProcessInfoSelf();
|
||||
|
||||
if (message == nullptr) {
|
||||
message = "";
|
||||
|
@ -494,15 +511,16 @@ uint64_t TRI_MicrosecondsTv(struct timeval* tv) {
|
|||
|
||||
#ifdef TRI_HAVE_LINUX_PROC
|
||||
|
||||
ProcessInfo TRI_ProcessInfoSelf() {
|
||||
TRI_process_info_t TRI_ProcessInfoSelf() {
|
||||
return TRI_ProcessInfo(Thread::currentProcessId());
|
||||
}
|
||||
|
||||
#elif ARANGODB_HAVE_GETRUSAGE
|
||||
|
||||
ProcessInfo TRI_ProcessInfoSelf() {
|
||||
ProcessInfo result;
|
||||
TRI_process_info_t TRI_ProcessInfoSelf() {
|
||||
TRI_process_info_t result;
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
result._scClkTck = 1000000;
|
||||
|
||||
struct rusage used;
|
||||
|
@ -590,9 +608,10 @@ static time_t _FileTime_to_POSIX(FILETIME* ft) {
|
|||
return (ts - 116444736000000000) / 10000000;
|
||||
}
|
||||
|
||||
ProcessInfo TRI_ProcessInfoSelf() {
|
||||
ProcessInfo result;
|
||||
TRI_process_info_t TRI_ProcessInfoSelf() {
|
||||
TRI_process_info_t result;
|
||||
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||
memset(&result, 0, sizeof(result));
|
||||
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
|
||||
// compiler warning wird in kauf genommen!c
|
||||
// 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
|
||||
|
||||
ProcessInfo TRI_ProcessInfo(TRI_pid_t pid) {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief contains all data documented by "proc"
|
||||
///
|
||||
/// @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;
|
||||
TRI_process_info_t TRI_ProcessInfo(TRI_pid_t pid) {
|
||||
TRI_process_info_t result;
|
||||
memset(&result, 0, sizeof(result));
|
||||
|
||||
char fn[1024];
|
||||
snprintf(fn, sizeof(fn), "/proc/%d/stat", pid);
|
||||
|
@ -821,9 +757,10 @@ ProcessInfo TRI_ProcessInfo(TRI_pid_t pid) {
|
|||
|
||||
#else
|
||||
|
||||
ProcessInfo TRI_ProcessInfo(TRI_pid_t pid) {
|
||||
ProcessInfo result;
|
||||
TRI_process_info_t TRI_ProcessInfo(TRI_pid_t pid) {
|
||||
TRI_process_info_t result;
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
result._scClkTck = 1;
|
||||
|
||||
return result;
|
||||
|
@ -845,21 +782,60 @@ void TRI_SetProcessTitle(char const* title) {
|
|||
/// @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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
||||
size_t n, bool usePipes,
|
||||
ExternalId* pid) {
|
||||
TRI_external_id_t* pid) {
|
||||
// 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) {
|
||||
// gracefully handle out of memory
|
||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(external, 0, sizeof(TRI_external_t));
|
||||
|
||||
external->_executable = TRI_DuplicateString(executable);
|
||||
external->_numberArguments = n + 1;
|
||||
|
||||
|
@ -869,7 +845,7 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
|||
if (external->_arguments == nullptr) {
|
||||
// gracefully handle out of memory
|
||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||
delete external;
|
||||
FreeExternal(external);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -892,7 +868,7 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
|||
|
||||
if (external->_status != TRI_EXT_RUNNING) {
|
||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||
delete external;
|
||||
FreeExternal(external);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -911,7 +887,7 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
|||
ExternalProcesses.push_back(external);
|
||||
} catch (...) {
|
||||
pid->_pid = TRI_INVALID_PROCESS_ID;
|
||||
delete external;
|
||||
FreeExternal(external);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -920,13 +896,13 @@ void TRI_CreateExternalProcess(char const* executable, char const** arguments,
|
|||
/// @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) {
|
||||
ExternalProcessStatus status;
|
||||
TRI_external_status_t status;
|
||||
status._status = TRI_EXT_NOT_FOUND;
|
||||
status._exitStatus = 0;
|
||||
|
||||
ExternalProcess* external = nullptr;
|
||||
TRI_external_t* external = nullptr;
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
||||
|
||||
|
@ -985,9 +961,6 @@ ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
|||
external->_exitStatus = 0;
|
||||
}
|
||||
} else if (res == -1) {
|
||||
if (errno == ECHILD) {
|
||||
external->_status = TRI_EXT_NOT_FOUND;
|
||||
}
|
||||
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "waitpid returned error for pid " << external->_pid << " ("
|
||||
<< wait << "): " << TRI_last_error();
|
||||
|
@ -1124,210 +1097,80 @@ ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
|||
}
|
||||
}
|
||||
|
||||
delete external;
|
||||
FreeExternal(external);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// @brief check for a process we didn't spawn, and check for access rights to
|
||||
// send it signals.
|
||||
#ifndef _WIN32
|
||||
static ExternalProcess* getExternalProcess(TRI_pid_t pid) {
|
||||
if (kill(pid, 0) == 0) {
|
||||
ExternalProcess* external = new ExternalProcess();
|
||||
static bool OurKillProcess(TRI_external_t* pid, int signal) {
|
||||
if (0 == kill(pid->_pid, signal)) {
|
||||
int count;
|
||||
|
||||
if (external == nullptr) {
|
||||
// gracefully handle out of memory
|
||||
return nullptr;
|
||||
// Otherwise we just let it be.
|
||||
for (count = 0; count < 10; count++) {
|
||||
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;
|
||||
}
|
||||
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) <<
|
||||
"checking for external process: '" << pid <<
|
||||
"' failed with error: " << strerror(errno);
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
#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;
|
||||
|
||||
UINT uExitCode = 0;
|
||||
|
||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
if (hProcess != nullptr) {
|
||||
ExternalProcess* external = new ExternalProcess();
|
||||
|
||||
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) {
|
||||
TerminateProcess(hProcess, uExitCode);
|
||||
CloseHandle(hProcess);
|
||||
return true;
|
||||
}
|
||||
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
|
||||
|
||||
#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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExternalProcessStatus TRI_KillExternalProcess(ExternalId pid, int signal, bool isTerminal) {
|
||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "Sending process: " << pid._pid << " the signal: " << signal;
|
||||
bool TRI_KillExternalProcess(TRI_external_id_t pid, int 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);
|
||||
|
||||
|
@ -1335,86 +1178,55 @@ ExternalProcessStatus TRI_KillExternalProcess(ExternalId pid, int signal, bool i
|
|||
++it) {
|
||||
if ((*it)->_pid == pid._pid) {
|
||||
external = (*it);
|
||||
ExternalProcesses.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isChild = (external != nullptr);
|
||||
if (!isChild) {
|
||||
external = getExternalProcess(pid._pid);
|
||||
if (external == nullptr) {
|
||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "kill: process not found: " << pid._pid << " in our starting table and it doesn't exist.";
|
||||
ExternalProcessStatus status;
|
||||
status._status = TRI_EXT_NOT_FOUND;
|
||||
status._exitStatus = -1;
|
||||
return status;
|
||||
}
|
||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "kill: process not found: " << pid._pid << " in our starting table - adding";
|
||||
if (external == nullptr) {
|
||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "kill: process not found: " << pid._pid;
|
||||
#ifndef _WIN32
|
||||
// Kill just in case:
|
||||
if (0 == kill(pid._pid, signal)) {
|
||||
// Otherwise we just let it be.
|
||||
for (int count = 0; count < 10; count++) {
|
||||
int loc;
|
||||
pid_t p;
|
||||
|
||||
// ok, we didn't spawn it, but now we claim the
|
||||
// ownership.
|
||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
||||
|
||||
try {
|
||||
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;
|
||||
}
|
||||
// And wait for it to avoid a zombie:
|
||||
sleep(1);
|
||||
p = waitpid(pid._pid, &loc, WUNTRACED | WNOHANG);
|
||||
if (p == pid._pid) {
|
||||
return true;
|
||||
}
|
||||
if (!isChild && (status._status == TRI_EXT_NOT_FOUND) ) {
|
||||
status._status = TRI_EXT_TERMINATED;
|
||||
status._errorMessage.clear();
|
||||
if (count == 8) {
|
||||
kill(pid._pid, SIGKILL);
|
||||
}
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_SuspendExternalProcess(ExternalId pid) {
|
||||
bool TRI_SuspendExternalProcess(TRI_external_id_t pid) {
|
||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "suspending process: " << pid._pid;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -1428,7 +1240,7 @@ bool TRI_SuspendExternalProcess(ExternalId pid) {
|
|||
/// @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;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -1483,7 +1295,19 @@ static uint64_t GetPhysicalMemory() {
|
|||
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
|
||||
|
||||
|
@ -1501,8 +1325,8 @@ void TRI_InitializeProcess() {
|
|||
|
||||
void TRI_ShutdownProcess() {
|
||||
MUTEX_LOCKER(mutexLocker, ExternalProcessesLock);
|
||||
for (auto* external : ExternalProcesses) {
|
||||
delete external;
|
||||
for (auto* e : ExternalProcesses) {
|
||||
FreeExternal(e);
|
||||
}
|
||||
ExternalProcesses.clear();
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ extern uint64_t TRI_PhysicalMemory;
|
|||
/// @brief returns information about the process
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ProcessInfo {
|
||||
typedef struct TRI_process_info_s {
|
||||
uint64_t _minorPageFaults;
|
||||
uint64_t _majorPageFaults;
|
||||
uint64_t _userTime;
|
||||
|
@ -56,9 +56,7 @@ struct ProcessInfo {
|
|||
int64_t _residentSize; // resident set size in number of bytes
|
||||
uint64_t _virtualSize;
|
||||
uint64_t _scClkTck;
|
||||
|
||||
ProcessInfo();
|
||||
};
|
||||
} TRI_process_info_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief status of an external process
|
||||
|
@ -80,27 +78,24 @@ typedef enum {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WIN32
|
||||
struct ExternalId {
|
||||
typedef struct TRI_external_id_s {
|
||||
TRI_pid_t _pid;
|
||||
int _readPipe;
|
||||
int _writePipe;
|
||||
ExternalId();
|
||||
};
|
||||
} TRI_external_id_t;
|
||||
#else
|
||||
struct ExternalId {
|
||||
typedef struct TRI_external_id_s {
|
||||
DWORD _pid;
|
||||
HANDLE _readPipe;
|
||||
HANDLE _writePipe;
|
||||
|
||||
ExternalId();
|
||||
};
|
||||
} TRI_external_id_t;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief external process description
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ExternalProcess {
|
||||
struct TRI_external_t {
|
||||
char* _executable;
|
||||
size_t _numberArguments;
|
||||
char** _arguments;
|
||||
|
@ -118,21 +113,16 @@ struct ExternalProcess {
|
|||
|
||||
TRI_external_status_e _status;
|
||||
int64_t _exitStatus;
|
||||
|
||||
~ExternalProcess();
|
||||
ExternalProcess();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief external process status
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ExternalProcessStatus {
|
||||
struct TRI_external_status_t {
|
||||
TRI_external_status_e _status;
|
||||
int64_t _exitStatus;
|
||||
std::string _errorMessage;
|
||||
|
||||
ExternalProcessStatus();
|
||||
};
|
||||
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProcessInfo TRI_ProcessInfoSelf(void);
|
||||
TRI_process_info_t TRI_ProcessInfoSelf(void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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
|
||||
|
@ -168,39 +158,32 @@ void TRI_SetProcessTitle(char const* title);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExternalProcessStatus TRI_CheckExternalProcess(ExternalId pid,
|
||||
TRI_external_status_t TRI_CheckExternalProcess(TRI_external_id_t pid,
|
||||
bool wait);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether a signal is expected to be terminal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TRI_IsDeadlySignal(int signal);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief kills an external process
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExternalProcessStatus TRI_KillExternalProcess(ExternalId pid,
|
||||
int signal,
|
||||
bool isTerminal);
|
||||
bool TRI_KillExternalProcess(TRI_external_id_t pid, int signal);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ContinueExternalProcess(ExternalId pid);
|
||||
bool TRI_ContinueExternalProcess(TRI_external_id_t pid);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initializes the process components
|
||||
|
|
|
@ -721,17 +721,3 @@ bool terminalKnowsANSIColors()
|
|||
// Windows 8 onwards the CMD window understands ANSI-Colorcodes.
|
||||
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();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// returns returns the filename in conjunction with a handle
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string getFileNameFromHandle(HANDLE fileHandle);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2367,7 +2367,7 @@ static void JS_ProcessStatistics(
|
|||
|
||||
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 rssp = 0;
|
||||
|
||||
|
@ -3384,106 +3384,6 @@ static void JS_HMAC(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3554,7 +3454,7 @@ static void JS_ExecuteExternal(
|
|||
usePipes = TRI_ObjectToBoolean(args[2]);
|
||||
}
|
||||
|
||||
ExternalId external;
|
||||
TRI_external_id_t external;
|
||||
TRI_CreateExternalProcess(*name, const_cast<char const**>(arguments),
|
||||
(size_t)n, usePipes, &external);
|
||||
if (arguments != nullptr) {
|
||||
|
@ -3570,9 +3470,39 @@ static void JS_ExecuteExternal(
|
|||
TRI_V8_THROW_ERROR("Process could not be started");
|
||||
}
|
||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||
|
||||
convertPipeStatus(args, result, external);
|
||||
|
||||
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
|
||||
TRI_V8_RETURN(result);
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
@ -3591,7 +3521,8 @@ static void JS_StatusExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
"statusExternal(<external-identifier>[, <wait>])");
|
||||
}
|
||||
|
||||
ExternalId pid;
|
||||
TRI_external_id_t pid;
|
||||
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||
|
||||
#ifndef _WIN32
|
||||
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]);
|
||||
}
|
||||
|
||||
ExternalProcessStatus external = TRI_CheckExternalProcess(pid, wait);
|
||||
TRI_external_status_t external = TRI_CheckExternalProcess(pid, wait);
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||
char const* status = "UNKNOWN";
|
||||
|
||||
result->Set(TRI_V8_ASCII_STRING(isolate, "status"),
|
||||
TRI_V8_STRING(isolate, convertProcessStatusToString(external)));
|
||||
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;
|
||||
}
|
||||
|
||||
result->Set(TRI_V8_ASCII_STRING(isolate, "status"), TRI_V8_STRING(isolate, status));
|
||||
|
||||
if (external._status == TRI_EXT_TERMINATED) {
|
||||
result->Set(
|
||||
|
@ -3627,6 +3585,7 @@ static void JS_StatusExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
TRI_V8_RETURN(result);
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a external program
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3693,7 +3652,7 @@ static void JS_ExecuteAndWaitExternal(
|
|||
usePipes = TRI_ObjectToBoolean(args[2]);
|
||||
}
|
||||
|
||||
ExternalId external;
|
||||
TRI_external_id_t external;
|
||||
TRI_CreateExternalProcess(*name, const_cast<char const**>(arguments),
|
||||
static_cast<size_t>(n), usePipes, &external);
|
||||
if (arguments != nullptr) {
|
||||
|
@ -3709,15 +3668,91 @@ static void JS_ExecuteAndWaitExternal(
|
|||
TRI_V8_THROW_ERROR("Process could not be started");
|
||||
}
|
||||
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;
|
||||
|
||||
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
|
||||
TRI_V8_RETURN(result);
|
||||
TRI_V8_TRY_CATCH_END
|
||||
|
@ -3734,22 +3769,14 @@ static void JS_KillExternal(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
// extract the arguments
|
||||
if (args.Length() < 1 || args.Length() > 2) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE(
|
||||
"killExternal(<external-identifier>[[, <signal>], isTerminal])");
|
||||
"killExternal(<external-identifier>, <signal>)");
|
||||
}
|
||||
int signal = SIGTERM;
|
||||
if (args.Length() >= 2) {
|
||||
if (args.Length() == 2) {
|
||||
signal = static_cast<int>(TRI_ObjectToInt64(args[1]));
|
||||
}
|
||||
|
||||
bool isTerminating;
|
||||
if (args.Length() >= 3) {
|
||||
isTerminating = TRI_ObjectToBoolean(args[2]);
|
||||
}
|
||||
else {
|
||||
isTerminating = TRI_IsDeadlySignal(signal);
|
||||
}
|
||||
|
||||
ExternalId pid;
|
||||
TRI_external_id_t pid;
|
||||
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||
|
||||
#ifndef _WIN32
|
||||
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
|
||||
|
||||
// return the result
|
||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||
ExternalId external;
|
||||
external._pid = pid._pid;
|
||||
|
||||
auto external_status = TRI_KillExternalProcess(pid, signal, isTerminating);
|
||||
|
||||
convertStatusToV8(args, result, external_status, external);
|
||||
|
||||
// return the result
|
||||
TRI_V8_RETURN(result);
|
||||
if (TRI_KillExternalProcess(pid, signal)) {
|
||||
TRI_V8_RETURN_TRUE();
|
||||
}
|
||||
TRI_V8_RETURN_FALSE();
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
|
@ -3785,7 +3806,8 @@ static void JS_SuspendExternal(
|
|||
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
|
||||
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>)");
|
||||
}
|
||||
|
||||
ExternalId pid;
|
||||
TRI_external_id_t pid;
|
||||
memset(&pid, 0, sizeof(TRI_external_id_t));
|
||||
|
||||
#ifndef _WIN32
|
||||
pid._pid = static_cast<TRI_pid_t>(TRI_ObjectToUInt64(args[0], true));
|
||||
|
|
Loading…
Reference in New Issue