From 85da36395b87665adfaccf4c9998e452817b11ee Mon Sep 17 00:00:00 2001 From: paulc Date: Tue, 5 May 2009 12:25:31 +0000 Subject: [PATCH] Added names to the Mutex class to ease debugging of deadlocks. git-svn-id: http://yate.null.ro/svn/yate/trunk@2611 acf43c95-373e-0410-b603-e72c3f656dc1 --- engine/Channel.cpp | 6 +++--- engine/Client.cpp | 12 ++++++------ engine/ClientLogic.cpp | 4 ++-- engine/DataFormat.cpp | 4 ++-- engine/Message.cpp | 3 ++- engine/Mutex.cpp | 40 ++++++++++++++++++++-------------------- engine/Socket.cpp | 2 +- engine/TelEngine.cpp | 8 ++++---- engine/Thread.cpp | 2 +- yatecbase.h | 2 +- yateclass.h | 8 ++------ 11 files changed, 44 insertions(+), 47 deletions(-) diff --git a/engine/Channel.cpp b/engine/Channel.cpp index d31529e7..21628866 100644 --- a/engine/Channel.cpp +++ b/engine/Channel.cpp @@ -62,11 +62,11 @@ bool TelEngine::isE164(const char* str) } static unsigned int s_callid = 0; -static Mutex s_callidMutex; +static Mutex s_callidMutex(false,"CallID"); // this is to protect against two threads trying to (dis)connect a pair // of call endpoints at the same time -static Mutex s_mutex(true); +static Mutex s_mutex(true,"CallEndpoint"); CallEndpoint::CallEndpoint(const char* id) : m_peer(0), m_id(id), m_mutex(0) @@ -851,7 +851,7 @@ const char* Module::messageName(int id) } Module::Module(const char* name, const char* type, bool earlyInit) - : Plugin(name,earlyInit), Mutex(true), + : Plugin(name,earlyInit), Mutex(true,"Module"), m_init(false), m_relays(0), m_name(name), m_type(type), m_changed(0) { debugName(m_name); diff --git a/engine/Client.cpp b/engine/Client.cpp index d34e26dc..9c4d35e6 100644 --- a/engine/Client.cpp +++ b/engine/Client.cpp @@ -148,9 +148,9 @@ static String s_rejectReason = "Rejected"; static String s_hangupReason = "User hangup"; static String s_cancelReason = "Cancelled"; static unsigned int s_eventLen = 0; // Log maximum lines (0: unlimited) -static Mutex s_debugMutex; -static Mutex s_proxyMutex; -static Mutex s_postponeMutex; +static Mutex s_debugMutex(false,"ClientDebug"); +static Mutex s_proxyMutex(false,"ClientProxy"); +static Mutex s_postponeMutex(false,"ClientPostpone"); static ObjList s_postponed; static NamedList* s_debugLog = 0; static ClientThreadProxy* s_proxy = 0; @@ -186,7 +186,7 @@ String ClientDriver::s_confName = "conf/client"; // The name of the client's con bool ClientDriver::s_dropConfPeer = true; // Drop a channel's old peer when terminated while in conference String ClientDriver::s_device; // Currently used audio device ObjList ClientSound::s_sounds; // ClientSound's list -Mutex ClientSound::s_soundsMutex(true); // ClientSound's list lock mutex +Mutex ClientSound::s_soundsMutex(true,"ClientSound"); // ClientSound's list lock mutex String ClientSound::s_calltoPrefix = "wave/play/"; // Client sound target prefix // Client relays @@ -3243,7 +3243,7 @@ ClientChannel* ClientDriver::findChanByPeer(const String& peer) // Constructor ClientAccount::ClientAccount(const char* proto, const char* user, const char* host, bool startup) - : Mutex(true), + : Mutex(true,"ClientAccount"), m_port(0), m_startup(startup), m_expires(-1), m_connected(false), m_resource(0) { @@ -3254,7 +3254,7 @@ ClientAccount::ClientAccount(const char* proto, const char* user, // Constructor. Build an account from a list of parameters. ClientAccount::ClientAccount(const NamedList& params) - : Mutex(true), + : Mutex(true,"ClientAccount"), m_port(0), m_startup(false), m_expires(-1), m_connected(false), m_resource(0) { diff --git a/engine/ClientLogic.cpp b/engine/ClientLogic.cpp index 6e459283..aed97e07 100644 --- a/engine/ClientLogic.cpp +++ b/engine/ClientLogic.cpp @@ -51,7 +51,7 @@ static unsigned int s_maxCallHistory = 20; ObjList ClientLogic::s_accOptions; ObjList ClientLogic::s_protocols; -Mutex ClientLogic::s_protocolsMutex(true); +Mutex ClientLogic::s_protocolsMutex(true,"ClientProtocols"); // Parameters that are applied from provider template const char* ClientLogic::s_provParams[] = { "server", @@ -177,7 +177,7 @@ inline void activatePageCalls(ClientLogic* logic, Window* wnd = 0) */ // Constructor ClientLogic::ClientLogic(const char* name, int priority) - : m_durationMutex(true), m_name(name), m_prio(priority) + : m_durationMutex(true,"ClientLogic::duration"), m_name(name), m_prio(priority) { Debug(ClientDriver::self(),DebugAll,"ClientLogic(%s) [%p]",m_name.c_str(),this); Client::addLogic(this); diff --git a/engine/DataFormat.cpp b/engine/DataFormat.cpp index 7b9278a4..b93e3913 100644 --- a/engine/DataFormat.cpp +++ b/engine/DataFormat.cpp @@ -109,7 +109,7 @@ static TranslatorCaps s_stereoCaps[] = { { 0, 0, 0 } }; -static Mutex s_dataMutex(true); +static Mutex s_dataMutex(true,"DataEndpoint"); class ThreadedSourcePrivate : public Thread { @@ -1079,7 +1079,7 @@ bool DataTranslator::synchronize(DataSource* source) return true; } -Mutex DataTranslator::s_mutex(true); +Mutex DataTranslator::s_mutex(true,"DataTranslator"); ObjList DataTranslator::s_factories; unsigned int DataTranslator::s_maxChain = 3; static ObjList s_compose; diff --git a/engine/Message.cpp b/engine/Message.cpp index a13e3f4b..70ac83b4 100644 --- a/engine/Message.cpp +++ b/engine/Message.cpp @@ -270,7 +270,8 @@ bool MessageRelay::receivedInternal(Message& msg) MessageDispatcher::MessageDispatcher() - : m_changes(0), m_warnTime(0) + : Mutex(false,"MessageDispatcher"), + m_changes(0), m_warnTime(0) { XDebug(DebugInfo,"MessageDispatcher::MessageDispatcher() [%p]",this); } diff --git a/engine/Mutex.cpp b/engine/Mutex.cpp index 6f95d1cf..5b128070 100644 --- a/engine/Mutex.cpp +++ b/engine/Mutex.cpp @@ -49,7 +49,7 @@ namespace TelEngine { class MutexPrivate { public: - MutexPrivate(bool recursive); + MutexPrivate(bool recursive, const char* name); ~MutexPrivate(); inline void ref() { ++m_refcount; } @@ -57,6 +57,8 @@ public: { if (!--m_refcount) delete this; } inline bool recursive() const { return m_recursive; } + inline const char* name() const + { return m_name; } bool locked() const { return (m_locked > 0); } bool lock(long maxwait); @@ -68,6 +70,7 @@ private: int m_refcount; volatile unsigned int m_locked; bool m_recursive; + const char* m_name; const char* m_owner; }; @@ -140,8 +143,9 @@ void GlobalMutex::unlock() } -MutexPrivate::MutexPrivate(bool recursive) - : m_refcount(1), m_locked(0), m_recursive(recursive), m_owner(0) +MutexPrivate::MutexPrivate(bool recursive, const char* name) + : m_refcount(1), m_locked(0), m_recursive(recursive), + m_name(name), m_owner(0) { GlobalMutex::lock(); s_count++; @@ -185,11 +189,11 @@ MutexPrivate::~MutexPrivate() #endif GlobalMutex::unlock(); if (m_locked) - Debug(DebugFail,"MutexPrivate owned by '%s' destroyed with %u locks [%p]", - m_owner,m_locked,this); + Debug(DebugFail,"MutexPrivate '%s' owned by '%s' destroyed with %u locks [%p]", + m_name,m_owner,m_locked,this); else if (warn) - Debug(DebugGoOn,"MutexPrivate owned by '%s' unlocked in destructor [%p]", - m_owner,this); + Debug(DebugGoOn,"MutexPrivate '%s' owned by '%s' unlocked in destructor [%p]", + m_name,m_owner,this); } bool MutexPrivate::lock(long maxwait) @@ -253,8 +257,8 @@ bool MutexPrivate::lock(long maxwait) deref(); GlobalMutex::unlock(); if (warn && !rval) - Debug(DebugFail,"Thread '%s' could not take lock owned by '%s' for %lu usec!", - Thread::currentName(),m_owner,maxwait); + Debug(DebugFail,"Thread '%s' could not lock mutex '%s' owned by '%s' for %lu usec!", + Thread::currentName(),m_name,m_owner,maxwait); return rval; } @@ -269,8 +273,8 @@ void MutexPrivate::unlock() if (!--m_locked) { const char* tname = thr ? thr->name() : 0; if (tname != m_owner) - Debug(DebugFail,"MutexPrivate unlocked by '%s' but owned by '%s' [%p]", - tname,m_owner,this); + Debug(DebugFail,"MutexPrivate '%s' unlocked by '%s' but owned by '%s' [%p]", + m_name,tname,m_owner,this); m_owner = 0; } int locks = --s_locks; @@ -288,21 +292,17 @@ void MutexPrivate::unlock() deref(); } else - Debug(DebugFail,"MutexPrivate::unlock called on unlocked mutex [%p]",this); + Debug(DebugFail,"MutexPrivate::unlock called on unlocked '%s' [%p]",m_name,this); GlobalMutex::unlock(); } -Mutex::Mutex() +Mutex::Mutex(bool recursive, const char* name) : m_private(0) { - m_private = new MutexPrivate(false); -} - -Mutex::Mutex(bool recursive) - : m_private(0) -{ - m_private = new MutexPrivate(recursive); + if (!name) + name = "?"; + m_private = new MutexPrivate(recursive,name); } Mutex::Mutex(const Mutex &original) diff --git a/engine/Socket.cpp b/engine/Socket.cpp index c8375fbf..9e66e097 100644 --- a/engine/Socket.cpp +++ b/engine/Socket.cpp @@ -74,7 +74,7 @@ using namespace TelEngine; -static Mutex s_mutex; +static Mutex s_mutex(false,"Socket"); #ifdef _WINDOWS diff --git a/engine/TelEngine.cpp b/engine/TelEngine.cpp index d896e66f..d6d904f0 100644 --- a/engine/TelEngine.cpp +++ b/engine/TelEngine.cpp @@ -47,7 +47,7 @@ void srandom(unsigned int seed) int _gmtime_s(struct tm* _tm, const time_t* time) { - static TelEngine::Mutex m; + static TelEngine::Mutex m(false,"_gmtime_s"); struct tm* tmp; if (!_tm) return EINVAL; @@ -142,8 +142,8 @@ static void dbg_colorize_func(const char* buf, int level) static void (*s_output)(const char*,int) = dbg_stderr_func; static void (*s_intout)(const char*,int) = 0; -static Mutex out_mux; -static Mutex ind_mux; +static Mutex out_mux(false,"DebugOutput"); +static Mutex ind_mux(false,"DebugIndent"); static Thread* s_thr = 0; static bool reentered() @@ -610,7 +610,7 @@ void GenObject::destruct() } -static Mutex s_refmutex; +static Mutex s_refmutex(false,"RefObject"); RefObject::~RefObject() { diff --git a/engine/Thread.cpp b/engine/Thread.cpp index 753ea2c5..9cb058c3 100644 --- a/engine/Thread.cpp +++ b/engine/Thread.cpp @@ -117,7 +117,7 @@ static TokenDict s_prio[] = { }; static ObjList s_threads; -static Mutex s_tmutex(true); +static Mutex s_tmutex(true,"Thread"); ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name,Thread::Priority prio) { diff --git a/yatecbase.h b/yatecbase.h index cc2eb2a8..c225d9e0 100644 --- a/yatecbase.h +++ b/yatecbase.h @@ -2840,7 +2840,7 @@ public: * @param name List's name used for debug purposes */ inline ClientAccountList(const char* name) - : String(name), Mutex(true) + : String(name), Mutex(true,"ClientAccountList") {} /** diff --git a/yateclass.h b/yateclass.h index 756a29ed..e4b1b0d0 100644 --- a/yateclass.h +++ b/yateclass.h @@ -3544,17 +3544,13 @@ class YATE_API Mutex { friend class MutexPrivate; public: - /** - * Construct a new unlocked fast mutex - */ - Mutex(); - /** * Construct a new unlocked mutex * @param recursive True if the mutex has to be recursive (reentrant), * false for a normal fast mutex + * @param name Static name of the mutex (for debugging purpose only) */ - Mutex(bool recursive); + Mutex(bool recursive = false, const char* name = 0); /** * Copy constructor creates a shared mutex