50using namespace blocxx;
57 bool g_useWaitpidThreadFix =
58#ifdef BLOCXX_WAITPID_THREADING_PROBLEM
66 OnceFlag g_initThreadGuard = BLOCXX_ONCE_INIT;
67 ProcessThread* g_processThread = 0;
71 Thread_t getWorkerThreadId();
77 bool rv = g_useWaitpidThreadFix;
78 g_useWaitpidThreadFix = enabled;
84 if (!g_useWaitpidThreadFix)
89 Thread_t workerThread = getWorkerThreadId();
119 NonRecursiveMutexLock lock(
m_mutex);
126 NonRecursiveMutexLock lock(
m_mutex);
143 class WorkItem :
public IntrusiveCountableBase
150 virtual void doWork() = 0;
157 void saveException(Exception* err)
163 Exception* getException()
166 return m_err.getPtr();
177 class SpawnWorkItem :
public WorkItem
180 SpawnWorkItem(
char const * execPath,
char const *
const argv[],
181 char const *
const envp[], Exec::PreExec & preExec)
189 virtual ~SpawnWorkItem()
193 virtual void doWork()
219 class WaitpidWorkItem :
public WorkItem
222 WaitpidWorkItem(const ::pid_t& pid)
227 virtual ~WaitpidWorkItem()
231 virtual void doWork()
237 Process::Status waitTillDone()
253 typedef IntrusiveReference<SpawnWorkItem> SpawnWorkItemPtr;
254 typedef IntrusiveReference<WaitpidWorkItem> WaitpidWorkItemPtr;
260 virtual ~WorkQueue() {}
273 WorkItem* newWork =
m_work.front();
279 void addWork(WorkItem* newWork)
296 class ProcessThread :
public Thread
300 virtual ~ProcessThread();
305 char const * exec_path,
306 char const *
const argv[],
307 char const *
const envp[],
308 Exec::PreExec & pre_exec
319 ProcessThread::ProcessThread()
323 ProcessThread::~ProcessThread()
328 Int32 ProcessThread::run()
342 newWork->saveException(e.clone());
344 newWork->signalDone();
351 ProcessRef ProcessThread::spawn(
char const * exec_path,
char const *
const argv[],
352 char const *
const envp[], Exec::PreExec & pre_exec)
354 SpawnWorkItemPtr newWork(
new SpawnWorkItem(exec_path, argv, envp, pre_exec));
359 Exception* err = newWork->getException();
368 Process::Status ProcessThread::waitPid(
const ProcId& pid)
370 WaitpidWorkItemPtr newWork(
new WaitpidWorkItem(pid));
373 Process::Status result = newWork->waitTillDone();
375 Exception* err = newWork->getException();
388 g_processThread =
new ProcessThread();
389 g_processThread->start();
392 Thread_t getWorkerThreadId()
394 callOnce(g_initThreadGuard, initThread);
395 return g_processThread->getId();
402 char const *
const argv[],
char const *
const envp[],
Exec::PreExec & pre_exec)
404 callOnce(g_initThreadGuard, initThread);
405 return g_processThread->spawn(exec_path, argv, envp, pre_exec);
410 callOnce(g_initThreadGuard, initThread);
411 return g_processThread->waitPid(pid);
NonRecursiveMutex m_mutex
NonRecursiveMutex m_errMutex
NonRecursiveMutex m_resultMutex
NonRecursiveMutex m_workMutex
const char *const * m_argv
const char *const * m_envp
NonRecursiveMutex m_idMutex
Exec::PreExec & m_preExec
std::queue< WorkItem * > m_work
This class is used to specify what spawn() should do between fork and exec.
ProcessRef spawn(char const *exec_path, char const *const argv[], char const *const envp[], PreExec &pre_exec)
Run the executable exec_path in a child process, with argv for the program arguments and envp for the...
bool sameThreads(const volatile Thread_t &handle1, const volatile Thread_t &handle2)
Check two platform dependant thread types for equality.
BLOCXX_COMMON_API ProcessRef spawnProcess(char const *exec_path, char const *const argv[], char const *const envp[], Exec::PreExec &pre_exec)
BLOCXX_COMMON_API Process::Status waitPid(const ProcId &pid)
BLOCXX_COMMON_API bool setWaitpidThreadFixEnabled(bool enabled)
If a program is single threaded (like the monitor code is), then this function can be called to ensur...
BLOCXX_COMMON_API bool shouldUseWaitpidThreadFix()
void BLOCXX_COMMON_API callOnce(OnceFlag &flag, FuncT F)
The first time callOnce is called with a given onceFlag argument, it calls func with no argument and ...
Process::Status pollStatusImpl(ProcId pid)
IntrusiveReference< Process > ProcessRef