1
0
Fork 0

Revert "rework process handling (#3322)"

This reverts commit c56e4949b9.
This commit is contained in:
Max Neunhoeffer 2017-09-28 15:25:05 +02:00
parent c56e4949b9
commit d2b62c99d6
6 changed files with 441 additions and 626 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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