40#include "blocxx/BLOCXX_config.h"
63#include "blocxx/WinProcessUtils.hpp"
74#ifdef BLOCXX_HAVE_UNISTD_H
78#if defined(sigemptyset)
103: m_status_available(pid > 0),
109: m_status_available(static_cast<bool>(rep1)),
173 return !m_status_available;
178 return m_status_available && (WIFEXITED(
m_status) || WIFSIGNALED(
m_status));
183 return m_status_available && WIFEXITED(
m_status);
198 return m_status_available && WIFSIGNALED(
m_status);
208 return m_status_available && WIFSTOPPED(
m_status);
220 rep1 =
static_cast<int>(m_status_available);
226 return exitTerminated() && exitStatus() == 0;
239 else if (terminated())
241 if (exitTerminated())
243 return Format(
"exited with status %1",
String(exitStatus()));
245 else if (signalTerminated())
270 return ::kill(pid,
sig) == 0 ? 0 : errno;
274 virtual Process::Status pollStatus(ProcId pid)
276 if (WaitpidThreadFix::shouldUseWaitpidThreadFix())
278 return WaitpidThreadFix::waitPid(pid);
285struct ZombieReaperPoolCreator
287 static ThreadPool* create(
int dummy)
289 return new ThreadPool(ThreadPool::DYNAMIC_SIZE, (std::numeric_limits<UInt32>::max)(), 0);
294class ZombieReaper :
public Runnable
297 ZombieReaper(ProcId pid,
const ProcessImplRef& impl)
304 Logger lgr(COMPONENT_NAME);
306 Process::Status status =
m_impl->pollStatus(
m_pid);
307 while (!status.terminated())
309 Thread::sleep(Timeout::relative(10));
329:
m_impl(new ChildProcessImpl())
353:
m_impl(new ChildProcessImpl())
374 Logger lgr(COMPONENT_NAME);
388 Logger lgr(COMPONENT_NAME);
504 if (!killProcess(killTimeout, terminationSelectionFlag))
518 if (!
killWait(sigkillTimeout, SIGKILL,
"SIGKILL", terminationSelectionFlag))
532 float const mult = 1.20;
533 float const max_period = 5000.0;
534 float period = 100.0;
539 period = (std::min)(max_period, period * mult);
554 DWORD rc1 = WaitForSingleObject(pid, 0);
555 if(rc1 == WAIT_FAILED)
562 BOOL rc = GetExitCodeProcess(pid, &exitCode);
571 return Process::Status(pid, exitCode);
576bool Process::terminateByMessage(
const Timeout& waitTime)
578 DWORD bsmApp = BSM_APPLICATIONS;
580 BOOL bSucceed = BroadcastSystemMessage(BSF_IGNORECURRENTTASK, &bsmApp, termMsg, NULL, NULL);
599bool Process::killProcess(
const Timeout& waitTime, ETerminationSelectionFlag terminationSelectionFlag)
601 DWORD result = ERROR_SUCCESS;
603 DWORD pId = WinUtils::getProcessIdNT(
m_pid);
606 result = WinUtils::killProcessGroup(pId);
610 result = WinUtils::killProcess(pId);
613 if (result != ERROR_SUCCESS)
632 return GetCurrentProcess();
645 wpid = ::waitpid(pid, &status, WNOHANG | WUNTRACED);
647 }
while (wpid < 0 && errno == EINTR);
673 Format fmt(
"Failed sending %1 to process %2.", signame,
m_pid);
674 char const * msg = fmt.
c_str();
#define BLOCXX_DEFINE_EXCEPTION(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
#define BLOCXX_GLOBAL_STRING_INIT(str)
#define BLOCXX_LAZY_GLOBAL_INIT(...)
Statically initialize a LazyGlobal instance.
#define BLOCXX_LOG_DEBUG(logger, message)
Log message to logger with the Debug level.
#define BLOCXX_INVALID_HANDLE
This class is the base of all exceptions thrown by BloCxx code.
This class can be used to store a global variable that is lazily initialized in a thread safe manner.
bool exitTerminated() const
String toString() const
Get a string representation of the status suitable for debugging or logging.
bool terminatedSuccessfully() const
bool signalTerminated() const
int getPOSIXwaitpidStatus() const
Get the result from waitpid()
void repr(int &rep1, int &rep2) const
ETerminationSelectionFlag
@ E_TERMINATE_PROCESS_GROUP
The process and any descendent processes which are in the process group will be terminated.
Process(UnnamedPipeRef const &in, UnnamedPipeRef const &out, UnnamedPipeRef const &err, ProcId pid)
void waitCloseTerm(const Timeout &wait_initial=Timeout::relative(5.0), const Timeout &wait_close=Timeout::relative(10.0), const Timeout &wait_term=Timeout::relative(15.0), ETerminationSelectionFlag terminationSelectionFlag=E_TERMINATE_PROCESS_GROUP)
Waits for the child process to terminate, taking increasingly severe measures to ensure that this hap...
UnnamedPipeRef out() const
Stdout for the child process.
ProcId pid() const
Process ID for the child process.
bool terminatesWithin(const Timeout &wait_time)
void release()
Releases ownership of the ProcId and UnnamedPipes held by this object.
virtual ~Process()
If release has been called on this object, does nothing.
UnnamedPipeRef in() const
Stdin for the child process.
UnnamedPipeRef err() const
Stderr for the child process.
bool killWait(const Timeout &wait_time, int sig, char const *signame, ETerminationSelectionFlag terminationSelectionFlag)
Abstract interface for abstracting details of dealing with a process.
virtual Process::Status pollStatus(ProcId pid)=0
virtual int kill(ProcId pid, int sig)=0
Sends signal sig to process pid.
This String class is an abstract data type that represents as NULL terminated string of characters.
static void sleep(UInt32 milliSeconds)
Suspend execution of the current thread until the given number of milliSeconds have elapsed.
The ThreadPool class is used to coordinate a group of threads.
A timeout can be absolute, which means that it will happen at the specified DateTime.
float getRelative() const
ETimeoutType getType() const
static Timeout relative(float seconds)
A TimeoutTimer is used by an algorithm to determine when a timeout has expired.
bool expired() const
Indicates whether the last loop time has exceeded the timeout.
void loop()
Meant to be called by timeout functions which loop, but don't want to reset the interval.
Timeout asAbsoluteTimeout() const
Converts the timer to an absolute timeout.
virtual int close()=0
Close the pipe.
const char * signalName(int sig)
String lastErrorMsg(bool socketError)
Process::Status pollStatusImpl(ProcId pid)
class BLOCXX_COMMON_API Logger
static const char * TERM_MESSAGE