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)
285struct ZombieReaperPoolCreator
287 static ThreadPool* create(
int dummy)
294class ZombieReaper :
public Runnable
307 while (!status.terminated())
329:
m_impl(new ChildProcessImpl())
353:
m_impl(new ChildProcessImpl())
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.
GlobalString COMPONENT_NAME
const char * signalName(int sig)
String lastErrorMsg(bool socketError)
BLOCXX_COMMON_API Process::Status waitPid(const ProcId &pid)
BLOCXX_COMMON_API bool shouldUseWaitpidThreadFix()
Process::Status pollStatusImpl(ProcId pid)
IntrusiveReference< ProcessImpl > ProcessImplRef
class BLOCXX_COMMON_API Logger
static const char * TERM_MESSAGE