Fixed a nasty bug in Linux TLS initialization.

Improved thread/mutex debugging.


git-svn-id: http://yate.null.ro/svn/yate/trunk@652 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2006-01-18 18:28:28 +00:00
parent 73e01366aa
commit 8faacfe499
4 changed files with 61 additions and 31 deletions

View File

@ -51,7 +51,8 @@ public:
: DataTranslator(sFormat,dFormat) { } : DataTranslator(sFormat,dFormat) { }
virtual void Consume(const DataBlock& data, unsigned long tStamp) virtual void Consume(const DataBlock& data, unsigned long tStamp)
{ {
ref(); if (!ref())
return;
if (getTransSource()) { if (getTransSource()) {
DataBlock oblock; DataBlock oblock;
if (oblock.convert(data, m_format, getTransSource()->getFormat())) { if (oblock.convert(data, m_format, getTransSource()->getFormat())) {
@ -228,10 +229,9 @@ bool DataSource::attach(DataConsumer* consumer, bool override)
{ {
DDebug(DebugAll,"DataSource [%p] attaching consumer%s [%p]", DDebug(DebugAll,"DataSource [%p] attaching consumer%s [%p]",
this,(override ? " as override" : ""),consumer); this,(override ? " as override" : ""),consumer);
if (!consumer) if (!(consumer && consumer->ref()))
return false; return false;
Lock lock(m_mutex); Lock lock(m_mutex);
consumer->ref();
if (override) { if (override) {
// adjust timestamp for possible gaps in data // adjust timestamp for possible gaps in data
int64_t dt = Time::now() - consumer->m_lastTsTime; int64_t dt = Time::now() - consumer->m_lastTsTime;
@ -355,7 +355,8 @@ bool DataEndpoint::connect(DataEndpoint* peer)
return true; return true;
DDebug(DebugInfo,"DataEndpoint '%s' connecting peer %p to [%p]",m_name.c_str(),peer,this); DDebug(DebugInfo,"DataEndpoint '%s' connecting peer %p to [%p]",m_name.c_str(),peer,this);
ref(); if (!ref())
return false;
disconnect(); disconnect();
peer->ref(); peer->ref();
peer->disconnect(); peer->disconnect();
@ -471,9 +472,12 @@ void DataEndpoint::setConsumer(DataConsumer* consumer)
DataSource *source = m_peer ? m_peer->getSource() : 0; DataSource *source = m_peer ? m_peer->getSource() : 0;
DataConsumer *temp = m_consumer; DataConsumer *temp = m_consumer;
if (consumer) { if (consumer) {
consumer->ref(); if (consumer->ref()) {
if (source) if (source)
DataTranslator::attachChain(source,consumer); DataTranslator::attachChain(source,consumer);
}
else
consumer = 0;
} }
m_consumer = consumer; m_consumer = consumer;
if (temp) { if (temp) {
@ -490,9 +494,12 @@ void DataEndpoint::setPeerRecord(DataConsumer* consumer)
DataSource *source = m_peer ? m_peer->getSource() : 0; DataSource *source = m_peer ? m_peer->getSource() : 0;
DataConsumer *temp = m_peerRecord; DataConsumer *temp = m_peerRecord;
if (consumer) { if (consumer) {
consumer->ref(); if (consumer->ref()) {
if (source) if (source)
DataTranslator::attachChain(source,consumer); DataTranslator::attachChain(source,consumer);
}
else
consumer = 0;
} }
m_peerRecord = consumer; m_peerRecord = consumer;
if (temp) { if (temp) {
@ -508,9 +515,12 @@ void DataEndpoint::setCallRecord(DataConsumer* consumer)
return; return;
DataConsumer *temp = m_callRecord; DataConsumer *temp = m_callRecord;
if (consumer) { if (consumer) {
consumer->ref(); if (consumer->ref()) {
if (m_source) if (m_source)
DataTranslator::attachChain(m_source,consumer); DataTranslator::attachChain(m_source,consumer);
}
else
consumer = 0;
} }
m_callRecord = consumer; m_callRecord = consumer;
if (temp) { if (temp) {

View File

@ -222,7 +222,13 @@ bool MutexPrivate::lock(long maxwait)
if (rval) { if (rval) {
s_locks++; s_locks++;
m_locked++; m_locked++;
m_owner = Thread::currentName(); Thread* thr = Thread::current();
if (thr) {
thr->m_locks++;
m_owner = thr->name();
}
else
m_owner = 0;
} }
else else
deref(); deref();
@ -238,6 +244,9 @@ void MutexPrivate::unlock()
// Hope we don't hit a bug related to the debug mutex! // Hope we don't hit a bug related to the debug mutex!
GlobalMutex::lock(); GlobalMutex::lock();
if (m_locked) { if (m_locked) {
Thread* thr = Thread::current();
if (thr)
thr->m_locks--;
if (!--m_locked) if (!--m_locked)
m_owner = 0; m_owner = 0;
if (--s_locks < 0) if (--s_locks < 0)

View File

@ -58,7 +58,6 @@ public:
bool m_updest; bool m_updest;
bool m_cancel; bool m_cancel;
const char* m_name; const char* m_name;
private:
#ifdef _WINDOWS #ifdef _WINDOWS
static void startFunc(void* arg); static void startFunc(void* arg);
#else #else
@ -66,7 +65,6 @@ private:
#endif #endif
static void cleanupFunc(void* arg); static void cleanupFunc(void* arg);
static void destroyFunc(void* arg); static void destroyFunc(void* arg);
static void keyAllocFunc();
}; };
}; };
@ -81,7 +79,18 @@ using namespace TelEngine;
DWORD tls_index = ::TlsAlloc(); DWORD tls_index = ::TlsAlloc();
#else #else
static pthread_key_t current_key; static pthread_key_t current_key;
static pthread_once_t current_key_once = PTHREAD_ONCE_INIT;
class ThreadPrivateKeyAlloc
{
public:
ThreadPrivateKeyAlloc()
{
if (::pthread_key_create(&current_key,ThreadPrivate::destroyFunc))
Debug(DebugFail,"Failed to create current thread key!");
}
};
static ThreadPrivateKeyAlloc keyAllocator;
#endif #endif
static TokenDict s_prio[] = { static TokenDict s_prio[] = {
@ -247,7 +256,6 @@ void ThreadPrivate::run()
#ifdef _WINDOWS #ifdef _WINDOWS
::TlsSetValue(tls_index,this); ::TlsSetValue(tls_index,this);
#else #else
::pthread_once(&current_key_once,keyAllocFunc);
::pthread_setspecific(current_key,this); ::pthread_setspecific(current_key,this);
pthread_cleanup_push(cleanupFunc,this); pthread_cleanup_push(cleanupFunc,this);
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0); ::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
@ -273,9 +281,10 @@ bool ThreadPrivate::cancel(bool hard)
ret = false; ret = false;
if (hard) { if (hard) {
#ifdef _WINDOWS #ifdef _WINDOWS
Debug(DebugFail,"ThreadPrivate terminating win32 thread %lu [%p]",thread,this); Debug(DebugGoOn,"ThreadPrivate terminating win32 thread %lu [%p]",thread,this);
ret = ::TerminateThread(reinterpret_cast<HANDLE>(thread),0) != 0; ret = ::TerminateThread(reinterpret_cast<HANDLE>(thread),0) != 0;
#else #else
Debug(DebugMild,"ThreadPrivate terminating pthread %p [%p]",&thread,this);
ret = !::pthread_cancel(thread); ret = !::pthread_cancel(thread);
#endif #endif
if (ret) { if (ret) {
@ -296,9 +305,11 @@ void ThreadPrivate::cleanup()
if (m_thread->m_private == this) { if (m_thread->m_private == this) {
m_thread->m_private = 0; m_thread->m_private = 0;
m_thread->cleanup(); m_thread->cleanup();
if (m_thread->locks())
Debug(DebugFail,"Thread '%s' destroyed with %d mutex locks [%p]",m_name,m_thread->locks(),m_thread);
} }
else { else {
Debug(DebugWarn,"ThreadPrivate::cleanup() %p '%s' mismatching %p [%p]",m_thread,m_name,m_thread->m_private,this); Debug(DebugFail,"ThreadPrivate::cleanup() %p '%s' mismatching %p [%p]",m_thread,m_name,m_thread->m_private,this);
m_thread = 0; m_thread = 0;
} }
} }
@ -390,15 +401,6 @@ void ThreadPrivate::cleanupFunc(void* arg)
t->cleanup(); t->cleanup();
} }
void ThreadPrivate::keyAllocFunc()
{
#ifndef _WINDOWS
DDebug(DebugAll,"ThreadPrivate::keyAllocFunc()");
if (::pthread_key_create(&current_key,destroyFunc))
Debug(DebugGoOn,"Failed to create current thread key!");
#endif
}
#ifdef _WINDOWS #ifdef _WINDOWS
void ThreadPrivate::startFunc(void* arg) void ThreadPrivate::startFunc(void* arg)
#else #else
@ -422,7 +424,7 @@ Runnable::~Runnable()
} }
Thread::Thread(const char* name, Priority prio) Thread::Thread(const char* name, Priority prio)
: m_private(0) : m_private(0), m_locks(0)
{ {
#ifdef DEBUG #ifdef DEBUG
Debugger debug("Thread::Thread","(\"%s\",%d) [%p]",name,prio,this); Debugger debug("Thread::Thread","(\"%s\",%d) [%p]",name,prio,this);
@ -431,7 +433,7 @@ Thread::Thread(const char* name, Priority prio)
} }
Thread::Thread(const char *name, const char* prio) Thread::Thread(const char *name, const char* prio)
: m_private(0) : m_private(0), m_locks(0)
{ {
#ifdef DEBUG #ifdef DEBUG
Debugger debug("Thread::Thread","(\"%s\",\"%s\") [%p]",name,prio,this); Debugger debug("Thread::Thread","(\"%s\",\"%s\") [%p]",name,prio,this);

View File

@ -2731,6 +2731,7 @@ public:
class YATE_API Thread : public Runnable class YATE_API Thread : public Runnable
{ {
friend class ThreadPrivate; friend class ThreadPrivate;
friend class MutexPrivate;
public: public:
/** /**
* Running priorities, their mapping is operating system dependent * Running priorities, their mapping is operating system dependent
@ -2766,6 +2767,13 @@ public:
*/ */
bool running() const; bool running() const;
/**
* Count how many Yate mutexes are kept locked by this thread
* @return Number of Mutex locks held by this thread
*/
inline int locks() const
{ return m_locks; }
/** /**
* Get the name of this thread * Get the name of this thread
* @return The pointer that was passed in the constructor * @return The pointer that was passed in the constructor
@ -2895,6 +2903,7 @@ protected:
private: private:
ThreadPrivate* m_private; ThreadPrivate* m_private;
int m_locks;
}; };
/** /**