diff --git a/js/client/modules/@arangodb/process-utils.js b/js/client/modules/@arangodb/process-utils.js index 9e95a28035..7e0672aea0 100644 --- a/js/client/modules/@arangodb/process-utils.js +++ b/js/client/modules/@arangodb/process-utils.js @@ -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!'); diff --git a/lib/Basics/process-utils.cpp b/lib/Basics/process-utils.cpp index e577a32ad6..1509e26420 100644 --- a/lib/Basics/process-utils.cpp +++ b/lib/Basics/process-utils.cpp @@ -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 ExternalProcesses; +static std::vector ExternalProcesses; //////////////////////////////////////////////////////////////////////////////// /// @brief lock for protected access to vector ExternalProcesses @@ -73,84 +162,6 @@ static std::vector 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_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(); } diff --git a/lib/Basics/process-utils.h b/lib/Basics/process-utils.h index 7ab1bc3fa7..5146f9eb48 100644 --- a/lib/Basics/process-utils.h +++ b/lib/Basics/process-utils.h @@ -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 diff --git a/lib/Basics/win-utils.cpp b/lib/Basics/win-utils.cpp index cd39014eb6..054011a4d3 100644 --- a/lib/Basics/win-utils.cpp +++ b/lib/Basics/win-utils.cpp @@ -721,17 +721,3 @@ bool terminalKnowsANSIColors() // Windows 8 onwards the CMD window understands ANSI-Colorcodes. return IsWindows8OrGreater(); } - -#include -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)); -} diff --git a/lib/Basics/win-utils.h b/lib/Basics/win-utils.h index 9d40a46d38..a5c5a59b80 100644 --- a/lib/Basics/win-utils.h +++ b/lib/Basics/win-utils.h @@ -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 diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index 73245193ef..b1258c9e29 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -2367,7 +2367,7 @@ static void JS_ProcessStatistics( v8::Handle 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 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 const& args, - v8::Handle &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 const& args, - v8::Handle &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( - 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( - 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(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 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 const& args) { "statusExternal([, ])"); } - ExternalId pid; + TRI_external_id_t pid; + memset(&pid, 0, sizeof(TRI_external_id_t)); #ifndef _WIN32 pid._pid = static_cast(TRI_ObjectToUInt64(args[0], true)); @@ -3603,12 +3534,39 @@ static void JS_StatusExternal(v8::FunctionCallbackInfo const& args) { wait = TRI_ObjectToBoolean(args[1]); } - ExternalProcessStatus external = TRI_CheckExternalProcess(pid, wait); + TRI_external_status_t external = TRI_CheckExternalProcess(pid, wait); v8::Handle 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 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(arguments), static_cast(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 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( + 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( + 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 const& args) { // extract the arguments if (args.Length() < 1 || args.Length() > 2) { TRI_V8_THROW_EXCEPTION_USAGE( - "killExternal([[, ], isTerminal])"); + "killExternal(, )"); } int signal = SIGTERM; - if (args.Length() >= 2) { + if (args.Length() == 2) { signal = static_cast(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_ObjectToUInt64(args[0], true)); @@ -3758,16 +3785,10 @@ static void JS_KillExternal(v8::FunctionCallbackInfo const& args) { #endif // return the result - v8::Handle 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()"); } - ExternalId pid; + TRI_external_id_t pid; + memset(&pid, 0, sizeof(TRI_external_id_t)); #ifndef _WIN32 pid._pid = static_cast(TRI_ObjectToUInt64(args[0], true)); @@ -3815,7 +3837,8 @@ static void JS_ContinueExternal( TRI_V8_THROW_EXCEPTION_USAGE("continueExternal()"); } - ExternalId pid; + TRI_external_id_t pid; + memset(&pid, 0, sizeof(TRI_external_id_t)); #ifndef _WIN32 pid._pid = static_cast(TRI_ObjectToUInt64(args[0], true));