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:
parent
edfe266f4d
commit
85da36395b
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
|
|
||||||
using namespace TelEngine;
|
using namespace TelEngine;
|
||||||
|
|
||||||
static Mutex s_mutex;
|
static Mutex s_mutex(false,"Socket");
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue