From: Lars Op den Kamp Date: Wed, 5 Oct 2011 21:13:48 +0000 (+0200) Subject: cec: fix some threading related bugs, like trying to join with a detached thread... X-Git-Tag: upstream/2.2.0~1^2~286 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=5559c36e3d98fa45d9731b843e60b4531a3a148a;p=deb_libcec.git cec: fix some threading related bugs, like trying to join with a detached thread. give each thread it's own condition. fixes deadlock on exit --- diff --git a/src/lib/platform/threads.cpp b/src/lib/platform/threads.cpp index 7c5b6ce..08a4c3b 100644 --- a/src/lib/platform/threads.cpp +++ b/src/lib/platform/threads.cpp @@ -63,7 +63,8 @@ void CMutex::Unlock(void) CLockObject::CLockObject(CMutex *mutex) : m_mutex(mutex) { - m_mutex->Lock(); + if (m_mutex) + m_mutex->Lock(); } CLockObject::~CLockObject(void) @@ -74,12 +75,14 @@ CLockObject::~CLockObject(void) void CLockObject::Leave(void) { - m_mutex->Unlock(); + if (m_mutex) + m_mutex->Unlock(); } void CLockObject::Lock(void) { - m_mutex->Lock(); + if (m_mutex) + m_mutex->Lock(); } CCondition::CCondition(void) @@ -93,34 +96,42 @@ CCondition::~CCondition(void) pthread_cond_destroy(&m_cond); } -void CCondition::Signal(void) +void CCondition::Broadcast(void) { pthread_cond_broadcast(&m_cond); } +void CCondition::Signal(void) +{ + pthread_cond_signal(&m_cond); +} + bool CCondition::Wait(CMutex *mutex, int64_t iTimeout) { bool bReturn(false); - struct timespec abstime; - struct timeval now; - if (gettimeofday(&now, NULL) == 0) + sched_yield(); + if (mutex) { - iTimeout += now.tv_usec / 1000; - abstime.tv_sec = now.tv_sec + (time_t)(iTimeout / 1000); - abstime.tv_nsec = (long)((iTimeout % (unsigned long)1000) * (unsigned long)1000000); - bReturn = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0); + struct timespec abstime; + struct timeval now; + if (gettimeofday(&now, NULL) == 0) + { + iTimeout += now.tv_usec / 1000; + abstime.tv_sec = now.tv_sec + (time_t)(iTimeout / 1000); + abstime.tv_nsec = (long)((iTimeout % (unsigned long)1000) * (unsigned long)1000000); + bReturn = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0); + } } return bReturn; } -void CCondition::Sleep(int iTimeout) +void CCondition::Sleep(int64_t iTimeout) { - sched_yield(); CCondition w; CMutex m; CLockObject lock(&m); - w.Wait(&m, int64_t(iTimeout)); + w.Wait(&m, iTimeout); } CThread::CThread(void) : @@ -132,6 +143,7 @@ CThread::CThread(void) : CThread::~CThread(void) { m_bStop = true; + m_threadCondition.Broadcast(); pthread_join(m_thread, NULL); } @@ -139,10 +151,11 @@ bool CThread::CreateThread(void) { bool bReturn(false); + CLockObject lock(&m_threadMutex); + m_bStop = false; if (!m_bRunning && pthread_create(&m_thread, NULL, (void *(*) (void *))&CThread::ThreadHandler, (void *)this) == 0) { m_bRunning = true; - pthread_detach(m_thread); bReturn = true; } @@ -151,14 +164,30 @@ bool CThread::CreateThread(void) void *CThread::ThreadHandler(CThread *thread) { + void *retVal = NULL; + if (thread) - return thread->Process(); - return NULL; + retVal = thread->Process(); + thread->m_bRunning = false; + + return retVal; } -void CThread::StopThread(bool bWaitForExit /* = true */) +bool CThread::StopThread(bool bWaitForExit /* = true */) { + bool bReturn(false); m_bStop = true; + + m_threadCondition.Broadcast(); + void *retVal; if (bWaitForExit) - pthread_join(m_thread, NULL); + bReturn = (pthread_join(m_thread, &retVal) == 0); + + return bReturn; +} + +bool CThread::Sleep(uint64_t iTimeout) +{ + CLockObject lock(&m_threadMutex); + return m_bStop ? false :m_threadCondition.Wait(&m_threadMutex, iTimeout); } diff --git a/src/lib/platform/threads.h b/src/lib/platform/threads.h index 4ae5ac7..8b0729d 100644 --- a/src/lib/platform/threads.h +++ b/src/lib/platform/threads.h @@ -32,6 +32,7 @@ */ #include "os-dependent.h" +#include namespace CEC { @@ -43,9 +44,10 @@ namespace CEC CCondition(void); virtual ~CCondition(void); + void Broadcast(void); void Signal(void); bool Wait(CMutex *mutex, int64_t iTimeout); - static void Sleep(int iTimeout); + static void Sleep(int64_t iTimeout); private: pthread_cond_t m_cond; @@ -87,14 +89,17 @@ namespace CEC virtual bool IsRunning(void) const { return m_bRunning; } virtual bool CreateThread(void); - virtual void StopThread(bool bWaitForExit = true); + virtual bool StopThread(bool bWaitForExit = true); + virtual bool Sleep(uint64_t iTimeout); static void *ThreadHandler(CThread *thread); virtual void *Process(void) = 0; protected: - pthread_t m_thread; - bool m_bRunning; - bool m_bStop; + pthread_t m_thread; + CMutex m_threadMutex; + CCondition m_threadCondition; + bool m_bRunning; + bool m_bStop; }; };