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

View File

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

View File

@ -58,7 +58,6 @@ public:
bool m_updest;
bool m_cancel;
const char* m_name;
private:
#ifdef _WINDOWS
static void startFunc(void* arg);
#else
@ -66,7 +65,6 @@ private:
#endif
static void cleanupFunc(void* arg);
static void destroyFunc(void* arg);
static void keyAllocFunc();
};
};
@ -81,7 +79,18 @@ using namespace TelEngine;
DWORD tls_index = ::TlsAlloc();
#else
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
static TokenDict s_prio[] = {
@ -247,7 +256,6 @@ void ThreadPrivate::run()
#ifdef _WINDOWS
::TlsSetValue(tls_index,this);
#else
::pthread_once(&current_key_once,keyAllocFunc);
::pthread_setspecific(current_key,this);
pthread_cleanup_push(cleanupFunc,this);
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
@ -273,9 +281,10 @@ bool ThreadPrivate::cancel(bool hard)
ret = false;
if (hard) {
#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;
#else
Debug(DebugMild,"ThreadPrivate terminating pthread %p [%p]",&thread,this);
ret = !::pthread_cancel(thread);
#endif
if (ret) {
@ -296,9 +305,11 @@ void ThreadPrivate::cleanup()
if (m_thread->m_private == this) {
m_thread->m_private = 0;
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 {
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;
}
}
@ -390,15 +401,6 @@ void ThreadPrivate::cleanupFunc(void* arg)
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
void ThreadPrivate::startFunc(void* arg)
#else
@ -422,7 +424,7 @@ Runnable::~Runnable()
}
Thread::Thread(const char* name, Priority prio)
: m_private(0)
: m_private(0), m_locks(0)
{
#ifdef DEBUG
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)
: m_private(0)
: m_private(0), m_locks(0)
{
#ifdef DEBUG
Debugger debug("Thread::Thread","(\"%s\",\"%s\") [%p]",name,prio,this);

View File

@ -2731,6 +2731,7 @@ public:
class YATE_API Thread : public Runnable
{
friend class ThreadPrivate;
friend class MutexPrivate;
public:
/**
* Running priorities, their mapping is operating system dependent
@ -2766,6 +2767,13 @@ public:
*/
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
* @return The pointer that was passed in the constructor
@ -2895,6 +2903,7 @@ protected:
private:
ThreadPrivate* m_private;
int m_locks;
};
/**