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
This commit is contained in:
paulc 2009-05-05 12:25:31 +00:00
parent edfe266f4d
commit 85da36395b
11 changed files with 44 additions and 47 deletions

View File

@ -62,11 +62,11 @@ bool TelEngine::isE164(const char* str)
} }
static unsigned int s_callid = 0; 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 // this is to protect against two threads trying to (dis)connect a pair
// of call endpoints at the same time // of call endpoints at the same time
static Mutex s_mutex(true); static Mutex s_mutex(true,"CallEndpoint");
CallEndpoint::CallEndpoint(const char* id) CallEndpoint::CallEndpoint(const char* id)
: m_peer(0), m_id(id), m_mutex(0) : 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) 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) m_init(false), m_relays(0), m_name(name), m_type(type), m_changed(0)
{ {
debugName(m_name); debugName(m_name);

View File

@ -148,9 +148,9 @@ static String s_rejectReason = "Rejected";
static String s_hangupReason = "User hangup"; static String s_hangupReason = "User hangup";
static String s_cancelReason = "Cancelled"; static String s_cancelReason = "Cancelled";
static unsigned int s_eventLen = 0; // Log maximum lines (0: unlimited) static unsigned int s_eventLen = 0; // Log maximum lines (0: unlimited)
static Mutex s_debugMutex; static Mutex s_debugMutex(false,"ClientDebug");
static Mutex s_proxyMutex; static Mutex s_proxyMutex(false,"ClientProxy");
static Mutex s_postponeMutex; static Mutex s_postponeMutex(false,"ClientPostpone");
static ObjList s_postponed; static ObjList s_postponed;
static NamedList* s_debugLog = 0; static NamedList* s_debugLog = 0;
static ClientThreadProxy* s_proxy = 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 bool ClientDriver::s_dropConfPeer = true; // Drop a channel's old peer when terminated while in conference
String ClientDriver::s_device; // Currently used audio device String ClientDriver::s_device; // Currently used audio device
ObjList ClientSound::s_sounds; // ClientSound's list 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 String ClientSound::s_calltoPrefix = "wave/play/"; // Client sound target prefix
// Client relays // Client relays
@ -3243,7 +3243,7 @@ ClientChannel* ClientDriver::findChanByPeer(const String& peer)
// Constructor // Constructor
ClientAccount::ClientAccount(const char* proto, const char* user, ClientAccount::ClientAccount(const char* proto, const char* user,
const char* host, bool startup) const char* host, bool startup)
: Mutex(true), : Mutex(true,"ClientAccount"),
m_port(0), m_startup(startup), m_expires(-1), m_connected(false), m_port(0), m_startup(startup), m_expires(-1), m_connected(false),
m_resource(0) m_resource(0)
{ {
@ -3254,7 +3254,7 @@ ClientAccount::ClientAccount(const char* proto, const char* user,
// Constructor. Build an account from a list of parameters. // Constructor. Build an account from a list of parameters.
ClientAccount::ClientAccount(const NamedList& params) ClientAccount::ClientAccount(const NamedList& params)
: Mutex(true), : Mutex(true,"ClientAccount"),
m_port(0), m_startup(false), m_expires(-1), m_connected(false), m_port(0), m_startup(false), m_expires(-1), m_connected(false),
m_resource(0) m_resource(0)
{ {

View File

@ -51,7 +51,7 @@ static unsigned int s_maxCallHistory = 20;
ObjList ClientLogic::s_accOptions; ObjList ClientLogic::s_accOptions;
ObjList ClientLogic::s_protocols; ObjList ClientLogic::s_protocols;
Mutex ClientLogic::s_protocolsMutex(true); Mutex ClientLogic::s_protocolsMutex(true,"ClientProtocols");
// Parameters that are applied from provider template // Parameters that are applied from provider template
const char* ClientLogic::s_provParams[] = { const char* ClientLogic::s_provParams[] = {
"server", "server",
@ -177,7 +177,7 @@ inline void activatePageCalls(ClientLogic* logic, Window* wnd = 0)
*/ */
// Constructor // Constructor
ClientLogic::ClientLogic(const char* name, int priority) 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); Debug(ClientDriver::self(),DebugAll,"ClientLogic(%s) [%p]",m_name.c_str(),this);
Client::addLogic(this); Client::addLogic(this);

View File

@ -109,7 +109,7 @@ static TranslatorCaps s_stereoCaps[] = {
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static Mutex s_dataMutex(true); static Mutex s_dataMutex(true,"DataEndpoint");
class ThreadedSourcePrivate : public Thread class ThreadedSourcePrivate : public Thread
{ {
@ -1079,7 +1079,7 @@ bool DataTranslator::synchronize(DataSource* source)
return true; return true;
} }
Mutex DataTranslator::s_mutex(true); Mutex DataTranslator::s_mutex(true,"DataTranslator");
ObjList DataTranslator::s_factories; ObjList DataTranslator::s_factories;
unsigned int DataTranslator::s_maxChain = 3; unsigned int DataTranslator::s_maxChain = 3;
static ObjList s_compose; static ObjList s_compose;

View File

@ -270,7 +270,8 @@ bool MessageRelay::receivedInternal(Message& msg)
MessageDispatcher::MessageDispatcher() MessageDispatcher::MessageDispatcher()
: m_changes(0), m_warnTime(0) : Mutex(false,"MessageDispatcher"),
m_changes(0), m_warnTime(0)
{ {
XDebug(DebugInfo,"MessageDispatcher::MessageDispatcher() [%p]",this); XDebug(DebugInfo,"MessageDispatcher::MessageDispatcher() [%p]",this);
} }

View File

@ -49,7 +49,7 @@ namespace TelEngine {
class MutexPrivate { class MutexPrivate {
public: public:
MutexPrivate(bool recursive); MutexPrivate(bool recursive, const char* name);
~MutexPrivate(); ~MutexPrivate();
inline void ref() inline void ref()
{ ++m_refcount; } { ++m_refcount; }
@ -57,6 +57,8 @@ public:
{ if (!--m_refcount) delete this; } { if (!--m_refcount) delete this; }
inline bool recursive() const inline bool recursive() const
{ return m_recursive; } { return m_recursive; }
inline const char* name() const
{ return m_name; }
bool locked() const bool locked() const
{ return (m_locked > 0); } { return (m_locked > 0); }
bool lock(long maxwait); bool lock(long maxwait);
@ -68,6 +70,7 @@ private:
int m_refcount; int m_refcount;
volatile unsigned int m_locked; volatile unsigned int m_locked;
bool m_recursive; bool m_recursive;
const char* m_name;
const char* m_owner; const char* m_owner;
}; };
@ -140,8 +143,9 @@ void GlobalMutex::unlock()
} }
MutexPrivate::MutexPrivate(bool recursive) MutexPrivate::MutexPrivate(bool recursive, const char* name)
: m_refcount(1), m_locked(0), m_recursive(recursive), m_owner(0) : m_refcount(1), m_locked(0), m_recursive(recursive),
m_name(name), m_owner(0)
{ {
GlobalMutex::lock(); GlobalMutex::lock();
s_count++; s_count++;
@ -185,11 +189,11 @@ MutexPrivate::~MutexPrivate()
#endif #endif
GlobalMutex::unlock(); GlobalMutex::unlock();
if (m_locked) if (m_locked)
Debug(DebugFail,"MutexPrivate owned by '%s' destroyed with %u locks [%p]", Debug(DebugFail,"MutexPrivate '%s' owned by '%s' destroyed with %u locks [%p]",
m_owner,m_locked,this); m_name,m_owner,m_locked,this);
else if (warn) else if (warn)
Debug(DebugGoOn,"MutexPrivate owned by '%s' unlocked in destructor [%p]", Debug(DebugGoOn,"MutexPrivate '%s' owned by '%s' unlocked in destructor [%p]",
m_owner,this); m_name,m_owner,this);
} }
bool MutexPrivate::lock(long maxwait) bool MutexPrivate::lock(long maxwait)
@ -253,8 +257,8 @@ bool MutexPrivate::lock(long maxwait)
deref(); deref();
GlobalMutex::unlock(); GlobalMutex::unlock();
if (warn && !rval) if (warn && !rval)
Debug(DebugFail,"Thread '%s' could not take lock owned by '%s' for %lu usec!", Debug(DebugFail,"Thread '%s' could not lock mutex '%s' owned by '%s' for %lu usec!",
Thread::currentName(),m_owner,maxwait); Thread::currentName(),m_name,m_owner,maxwait);
return rval; return rval;
} }
@ -269,8 +273,8 @@ void MutexPrivate::unlock()
if (!--m_locked) { if (!--m_locked) {
const char* tname = thr ? thr->name() : 0; const char* tname = thr ? thr->name() : 0;
if (tname != m_owner) if (tname != m_owner)
Debug(DebugFail,"MutexPrivate unlocked by '%s' but owned by '%s' [%p]", Debug(DebugFail,"MutexPrivate '%s' unlocked by '%s' but owned by '%s' [%p]",
tname,m_owner,this); m_name,tname,m_owner,this);
m_owner = 0; m_owner = 0;
} }
int locks = --s_locks; int locks = --s_locks;
@ -288,21 +292,17 @@ void MutexPrivate::unlock()
deref(); deref();
} }
else 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(); GlobalMutex::unlock();
} }
Mutex::Mutex() Mutex::Mutex(bool recursive, const char* name)
: m_private(0) : m_private(0)
{ {
m_private = new MutexPrivate(false); if (!name)
} name = "?";
m_private = new MutexPrivate(recursive,name);
Mutex::Mutex(bool recursive)
: m_private(0)
{
m_private = new MutexPrivate(recursive);
} }
Mutex::Mutex(const Mutex &original) Mutex::Mutex(const Mutex &original)

View File

@ -74,7 +74,7 @@
using namespace TelEngine; using namespace TelEngine;
static Mutex s_mutex; static Mutex s_mutex(false,"Socket");
#ifdef _WINDOWS #ifdef _WINDOWS

View File

@ -47,7 +47,7 @@ void srandom(unsigned int seed)
int _gmtime_s(struct tm* _tm, const time_t* time) int _gmtime_s(struct tm* _tm, const time_t* time)
{ {
static TelEngine::Mutex m; static TelEngine::Mutex m(false,"_gmtime_s");
struct tm* tmp; struct tm* tmp;
if (!_tm) if (!_tm)
return EINVAL; 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_output)(const char*,int) = dbg_stderr_func;
static void (*s_intout)(const char*,int) = 0; static void (*s_intout)(const char*,int) = 0;
static Mutex out_mux; static Mutex out_mux(false,"DebugOutput");
static Mutex ind_mux; static Mutex ind_mux(false,"DebugIndent");
static Thread* s_thr = 0; static Thread* s_thr = 0;
static bool reentered() static bool reentered()
@ -610,7 +610,7 @@ void GenObject::destruct()
} }
static Mutex s_refmutex; static Mutex s_refmutex(false,"RefObject");
RefObject::~RefObject() RefObject::~RefObject()
{ {

View File

@ -117,7 +117,7 @@ static TokenDict s_prio[] = {
}; };
static ObjList s_threads; 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) ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name,Thread::Priority prio)
{ {

View File

@ -2840,7 +2840,7 @@ public:
* @param name List's name used for debug purposes * @param name List's name used for debug purposes
*/ */
inline ClientAccountList(const char* name) inline ClientAccountList(const char* name)
: String(name), Mutex(true) : String(name), Mutex(true,"ClientAccountList")
{} {}
/** /**

View File

@ -3544,17 +3544,13 @@ class YATE_API Mutex
{ {
friend class MutexPrivate; friend class MutexPrivate;
public: public:
/**
* Construct a new unlocked fast mutex
*/
Mutex();
/** /**
* Construct a new unlocked mutex * Construct a new unlocked mutex
* @param recursive True if the mutex has to be recursive (reentrant), * @param recursive True if the mutex has to be recursive (reentrant),
* false for a normal fast mutex * 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 * Copy constructor creates a shared mutex