45 #include <sys/types.h>
50 using namespace blocxx;
52 namespace BLOCXX_NAMESPACE
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();
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();
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);