Protect the xptiWorkingSet's tables with a lock. (Bug 627985, bug 614480); r=dbaron,bsmedberg

This commit is contained in:
L. David Baron ext:(%2C%20Ehsan%20Akhgari%20%3Cehsan%40mozilla.com%3E) 2011-04-10 17:12:52 -04:00
parent cfaae0f225
commit 30255aeb19
5 changed files with 49 additions and 36 deletions

View File

@ -619,7 +619,10 @@ xptiInterfaceEntry::HasAncestor(const nsIID * iid, PRBool *_retval)
nsresult
xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
{
MonitorAutoEnter lock(xptiInterfaceInfoManager::GetInfoMonitor());
#ifdef DEBUG
xptiInterfaceInfoManager::GetSingleton()->GetWorkingSet()->mTableMonitor.
AssertCurrentThreadIn();
#endif
LOG_INFO_MONITOR_ENTRY;
if(!mInfo)
@ -646,6 +649,19 @@ xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
}
}
PRBool
xptiInterfaceInfo::BuildParent()
{
mozilla::MonitorAutoEnter monitor(xptiInterfaceInfoManager::GetSingleton()->
GetWorkingSet()->mTableMonitor);
NS_ASSERTION(mEntry &&
mEntry->IsFullyResolved() &&
!mParent &&
mEntry->Parent(),
"bad BuildParent call");
return NS_SUCCEEDED(mEntry->Parent()->GetInterfaceInfo(&mParent));
}
/***************************************************************************/
NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
@ -679,9 +695,11 @@ xptiInterfaceInfo::Release(void)
NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
if(!cnt)
{
MonitorAutoEnter lock(xptiInterfaceInfoManager::GetInfoMonitor());
mozilla::MonitorAutoEnter monitor(xptiInterfaceInfoManager::
GetSingleton()->GetWorkingSet()->
mTableMonitor);
LOG_INFO_MONITOR_ENTRY;
// If GetInterfaceInfo added and *released* a reference before we
// acquired the monitor then 'this' might already be dead. In that
// case we would not want to try to access any instance data. We
@ -695,7 +713,7 @@ xptiInterfaceInfo::Release(void)
// then we want to bail out of here without destorying the object.
if(mRefCnt)
return 1;
if(mEntry)
{
mEntry->LockedInterfaceInfoDeathNotification();

View File

@ -80,8 +80,6 @@ xptiInterfaceInfoManager::FreeInterfaceInfoManager()
xptiInterfaceInfoManager::xptiInterfaceInfoManager()
: mWorkingSet(),
mResolveLock("xptiInterfaceInfoManager.mResolveLock"),
mAutoRegLock("xptiInterfaceInfoManager.mAutoRegLock"), // FIXME: unused!
mInfoMonitor("xptiInterfaceInfoManager.mInfoMonitor"),
mAdditionalManagersLock(
"xptiInterfaceInfoManager.mAdditionalManagersLock")
{
@ -235,6 +233,7 @@ xptiInterfaceInfoManager::RegisterXPTHeader(XPTHeader* aHeader)
xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader);
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
for(PRUint16 k = 0; k < aHeader->num_interfaces; k++)
VerifyAndAddEntryIfNew(aHeader->interface_directory + k, k, typelib);
}
@ -255,6 +254,7 @@ xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* ifa
if (!iface->interface_descriptor)
return;
mWorkingSet.mTableMonitor.AssertCurrentThreadIn();
xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->iid);
if (entry) {
// XXX validate this info to find possible inconsistencies
@ -306,6 +306,7 @@ EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
xptiInterfaceEntry*
xptiInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid)
{
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
return mWorkingSet.mIIDTable.Get(*iid);
}
@ -315,7 +316,8 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInte
NS_ASSERTION(iid, "bad param");
NS_ASSERTION(_retval, "bad param");
xptiInterfaceEntry* entry = GetInterfaceEntryForIID(iid);
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
return EntryToInfo(entry, _retval);
}
@ -325,6 +327,7 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForName(const char *name, nsIInte
NS_ASSERTION(name, "bad param");
NS_ASSERTION(_retval, "bad param");
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
return EntryToInfo(entry, _retval);
}
@ -335,7 +338,7 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetIIDForName(const char *name, nsIID *
NS_ASSERTION(name, "bad param");
NS_ASSERTION(_retval, "bad param");
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
if (!entry) {
*_retval = nsnull;
@ -351,6 +354,7 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **
NS_ASSERTION(iid, "bad param");
NS_ASSERTION(_retval, "bad param");
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
if (!entry) {
*_retval = nsnull;
@ -384,6 +388,7 @@ NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator **_ret
if (!array)
return NS_ERROR_UNEXPECTED;
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
mWorkingSet.mNameTable.EnumerateRead(xpti_ArrayAppender, array);
return array->Enumerate(_retval);
@ -419,6 +424,7 @@ NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(c
if (!array)
return NS_ERROR_UNEXPECTED;
MonitorAutoEnter monitor(mWorkingSet.mTableMonitor);
ArrayAndPrefix args = {array, prefix, PL_strlen(prefix)};
mWorkingSet.mNameTable.EnumerateRead(xpti_ArrayPrefixAppender, &args);

View File

@ -41,6 +41,8 @@
#include "xptiprivate.h"
using namespace mozilla;
// static
xptiTypelibGuts*
xptiTypelibGuts::Create(XPTHeader* aHeader)
@ -73,10 +75,13 @@ xptiTypelibGuts::GetEntryAt(PRUint16 i)
xptiWorkingSet* set =
xptiInterfaceInfoManager::GetSingleton()->GetWorkingSet();
if (iface->iid.Equals(zeroIID))
r = set->mNameTable.Get(iface->name);
else
r = set->mIIDTable.Get(iface->iid);
{
MonitorAutoEnter monitor(set->mTableMonitor);
if (iface->iid.Equals(zeroIID))
r = set->mNameTable.Get(iface->name);
else
r = set->mIIDTable.Get(iface->iid);
}
if (r)
SetEntryAt(i, r);

View File

@ -48,6 +48,7 @@ using namespace mozilla;
#define XPTI_HASHTABLE_SIZE 2048
xptiWorkingSet::xptiWorkingSet()
: mTableMonitor("xptiWorkingSet::mTableMonitor")
{
MOZ_COUNT_CTOR(xptiWorkingSet);
@ -68,7 +69,7 @@ xpti_Invalidator(const char* keyname, xptiInterfaceEntry* entry, void* arg)
void
xptiWorkingSet::InvalidateInterfaceInfos()
{
MonitorAutoEnter lock(xptiInterfaceInfoManager::GetInfoMonitor());
MonitorAutoEnter monitor(mTableMonitor);
mNameTable.EnumerateRead(xpti_Invalidator, NULL);
}

View File

@ -180,6 +180,11 @@ private:
public:
// XXX make these private with accessors
// mTableMonitor must be held across:
// * any read from or write to mIIDTable or mNameTable
// * any writing to the links between an xptiInterfaceEntry
// and its xptiInterfaceInfo (mEntry/mInfo)
mozilla::Monitor mTableMonitor;
nsDataHashtable<nsIDHashKey, xptiInterfaceEntry*> mIIDTable;
nsDataHashtable<nsDepCharHashKey, xptiInterfaceEntry*> mNameTable;
};
@ -406,15 +411,7 @@ private:
return mEntry && mEntry->EnsureResolved();
}
PRBool BuildParent()
{
NS_ASSERTION(mEntry &&
mEntry->IsFullyResolved() &&
!mParent &&
mEntry->Parent(),
"bad BuildParent call");
return NS_SUCCEEDED(mEntry->Parent()->GetInterfaceInfo(&mParent));
}
PRBool BuildParent();
xptiInterfaceInfo(); // not implemented
@ -451,18 +448,6 @@ public:
return self->mResolveLock;
}
static Mutex& GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull)
{
self = self ? self : GetSingleton();
return self->mAutoRegLock;
}
static Monitor& GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull)
{
self = self ? self : GetSingleton();
return self->mInfoMonitor;
}
xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
private:
@ -482,8 +467,6 @@ private:
private:
xptiWorkingSet mWorkingSet;
Mutex mResolveLock;
Mutex mAutoRegLock;
Monitor mInfoMonitor;
Mutex mAdditionalManagersLock;
nsCOMArray<nsISupports> mAdditionalManagers;
};