Bug 456705 - Firefox 2.0.0.17 crashes when opening a https-site or on shutdown with FoxyProxy 2.8.5 [@ nsSSLThread::Run], r=kaie

This commit is contained in:
Honza Bambas 2009-02-28 15:06:40 +01:00
parent a9919cef88
commit c618668c6d
5 changed files with 208 additions and 70 deletions

View File

@ -275,8 +275,68 @@ nsTokenEventRunnable::Run()
return nssComponent->DispatchEvent(mType, mTokenName);
}
// We must ensure that the nsNSSComponent has been loaded before
// creating any other components.
PRBool EnsureNSSInitialized(EnsureNSSOperator op)
{
static PRBool loading = PR_FALSE;
static PRBool haveLoaded = PR_FALSE;
switch (op)
{
// In following 4 cases we are protected by monitor of XPCOM component
// manager - we are inside of do_GetService call for nss component, so it is
// safe to move with the flags here.
case nssLoading:
if (loading)
return PR_FALSE; // We are reentered during nss component creation
loading = PR_TRUE;
return PR_TRUE;
case nssInitSucceeded:
NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
loading = PR_FALSE;
haveLoaded = PR_TRUE;
return PR_TRUE;
case nssInitFailed:
NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)");
loading = PR_FALSE;
// no break
case nssShutdown:
haveLoaded = PR_FALSE;
return PR_FALSE;
// In this case we are called from a component to ensure nss initilization.
// If the component has not yet been loaded and is not currently loading
// call do_GetService for nss component to ensure it.
case nssEnsure:
// We are reentered during nss component creation or nss component is already up
if (haveLoaded || loading)
return PR_TRUE;
{
nsCOMPtr<nsISupports> nssComponent
= do_GetService(PSM_COMPONENT_CONTRACTID);
// Nss component failed to initialize, inform the caller of that fact.
// Flags are appropriately set by component constructor itself.
if (!nssComponent)
return PR_FALSE;
return PR_TRUE;
}
default:
NS_ASSERTION(PR_FALSE, "Bad operator to EnsureNSSInitialized");
return PR_FALSE;
}
}
nsNSSComponent::nsNSSComponent()
:mNSSInitialized(PR_FALSE), mThreadList(nsnull)
:mNSSInitialized(PR_FALSE), mThreadList(nsnull),
mSSLThread(NULL), mCertVerificationThread(NULL)
{
mutex = PR_NewLock();
@ -296,19 +356,11 @@ nsNSSComponent::nsNSSComponent()
// registering all identity data until first needed.
memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
nsSSLIOLayerHelpers::Init();
NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
++mInstanceCount;
hashTableCerts = nsnull;
mShutdownObjectList = nsNSSShutDownList::construct();
mIsNetworkDown = PR_FALSE;
mSSLThread = new nsSSLThread();
if (mSSLThread)
mSSLThread->startThread();
mCertVerificationThread = new nsCertVerificationThread();
if (mCertVerificationThread)
mCertVerificationThread->startThread();
}
nsNSSComponent::~nsNSSComponent()
@ -357,6 +409,10 @@ nsNSSComponent::~nsNSSComponent()
mutex = nsnull;
}
// We are being freed, drop the haveLoaded flag to re-enable
// potential nss initialization later.
EnsureNSSInitialized(nssShutdown);
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
}
@ -1470,9 +1526,6 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
return NS_ERROR_FAILURE;
}
hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
certHashtable_valueCompare, 0, 0 );
nsresult rv;
nsCAutoString profileStr;
nsCOMPtr<nsIFile> profilePath;
@ -1521,6 +1574,9 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
if (NS_FAILED(rv))
return rv;
hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
certHashtable_valueCompare, 0, 0 );
#if defined(XP_MACOSX)
// function may modify the parameters
// ignore return code from conversion, we continue anyway
@ -1710,8 +1766,7 @@ nsNSSComponent::Init()
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
if (!mutex || !mShutdownObjectList ||
!mSSLThread || !mCertVerificationThread)
if (!mutex || !mShutdownObjectList)
{
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n"));
return NS_ERROR_OUT_OF_MEMORY;
@ -1747,9 +1802,30 @@ nsNSSComponent::Init()
rv = InitializeNSS(PR_TRUE); // ok to show a warning box on failure
if (NS_FAILED(rv)) {
PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
DeregisterObservers();
mPIPNSSBundle = nsnull;
return rv;
}
nsSSLIOLayerHelpers::Init();
mSSLThread = new nsSSLThread();
if (mSSLThread)
mSSLThread->startThread();
mCertVerificationThread = new nsCertVerificationThread();
if (mCertVerificationThread)
mCertVerificationThread->startThread();
if (!mSSLThread || !mCertVerificationThread)
{
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n"));
DeregisterObservers();
mPIPNSSBundle = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
InitializeCRLUpdateTimer();
RegisterPSMContentListener();
@ -2186,6 +2262,31 @@ nsNSSComponent::RegisterObservers()
return NS_OK;
}
nsresult
nsNSSComponent::DeregisterObservers()
{
if (!mObserversRegistered)
return NS_OK;
nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
NS_ASSERTION(observerService, "could not get observer service");
if (observerService) {
mObserversRegistered = PR_FALSE;
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: removing observers\n"));
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->RemoveObserver(this, PROFILE_APPROVE_CHANGE_TOPIC);
observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC);
observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC);
observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
observerService->RemoveObserver(this, PROFILE_AFTER_CHANGE_TOPIC);
observerService->RemoveObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC);
observerService->RemoveObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSComponent::RememberCert(CERTCertificate *cert)
{

View File

@ -93,6 +93,17 @@
#define NS_CRYPTO_HMAC_CLASSNAME "Mozilla Crypto HMAC Function Component"
#define NS_CRYPTO_HMAC_CID {0xa496d0a2, 0xdff7, 0x4e23, {0xbd, 0x65, 0x1c, 0xa7, 0x42, 0xfa, 0x17, 0x8a}}
enum EnsureNSSOperator
{
nssLoading = 0,
nssInitSucceeded = 1,
nssInitFailed = 2,
nssShutdown = 3,
nssEnsure = 4
};
extern PRBool EnsureNSSInitialized(EnsureNSSOperator op);
//--------------------------------------------
// Now we need a content listener to register
//--------------------------------------------
@ -287,6 +298,7 @@ private:
nsresult ConfigureInternalPKCS11Token();
nsresult RegisterPSMContentListener();
nsresult RegisterObservers();
nsresult DeregisterObservers();
nsresult DownloadCrlSilently();
nsresult PostCRLImportEvent(const nsCSubstring &urlString, nsIStreamListener *psmDownloader);
nsresult getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key);

View File

@ -777,8 +777,10 @@ void nsSSLIOLayerHelpers::Cleanup()
if (mSharedPollableEvent)
PR_DestroyPollableEvent(mSharedPollableEvent);
if (mutex)
if (mutex) {
PR_DestroyLock(mutex);
mutex = nsnull;
}
}
static nsresult
@ -1771,6 +1773,7 @@ nsSSLIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
return nsSSLThread::requestPoll(socketInfo, in_flags, out_flags);
}
PRBool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = PR_FALSE;
PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity;
PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods;
PRLock *nsSSLIOLayerHelpers::mutex = nsnull;
@ -1932,40 +1935,43 @@ static PRStatus PR_CALLBACK PSMConnectcontinue(PRFileDesc *fd, PRInt16 out_flags
nsresult nsSSLIOLayerHelpers::Init()
{
nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer");
nsSSLIOLayerMethods = *PR_GetDefaultIOMethods();
if (!nsSSLIOLayerInitialized) {
nsSSLIOLayerInitialized = PR_TRUE;
nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer");
nsSSLIOLayerMethods = *PR_GetDefaultIOMethods();
nsSSLIOLayerMethods.available = (PRAvailableFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.available64 = (PRAvailable64FN)_PSM_InvalidInt64;
nsSSLIOLayerMethods.fsync = (PRFsyncFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.seek = (PRSeekFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.seek64 = (PRSeek64FN)_PSM_InvalidInt64;
nsSSLIOLayerMethods.fileInfo = (PRFileInfoFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.fileInfo64 = (PRFileInfo64FN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.writev = (PRWritevFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.accept = (PRAcceptFN)_PSM_InvalidDesc;
nsSSLIOLayerMethods.bind = (PRBindFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.listen = (PRListenFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.shutdown = (PRShutdownFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.recvfrom = (PRRecvfromFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.sendto = (PRSendtoFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.acceptread = (PRAcceptreadFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.transmitfile = (PRTransmitfileFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.sendfile = (PRSendfileFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.available = (PRAvailableFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.available64 = (PRAvailable64FN)_PSM_InvalidInt64;
nsSSLIOLayerMethods.fsync = (PRFsyncFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.seek = (PRSeekFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.seek64 = (PRSeek64FN)_PSM_InvalidInt64;
nsSSLIOLayerMethods.fileInfo = (PRFileInfoFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.fileInfo64 = (PRFileInfo64FN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.writev = (PRWritevFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.accept = (PRAcceptFN)_PSM_InvalidDesc;
nsSSLIOLayerMethods.bind = (PRBindFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.listen = (PRListenFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.shutdown = (PRShutdownFN)_PSM_InvalidStatus;
nsSSLIOLayerMethods.recvfrom = (PRRecvfromFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.sendto = (PRSendtoFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.acceptread = (PRAcceptreadFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.transmitfile = (PRTransmitfileFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.sendfile = (PRSendfileFN)_PSM_InvalidInt;
nsSSLIOLayerMethods.getsockname = PSMGetsockname;
nsSSLIOLayerMethods.getpeername = PSMGetpeername;
nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption;
nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption;
nsSSLIOLayerMethods.recv = PSMRecv;
nsSSLIOLayerMethods.send = PSMSend;
nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue;
nsSSLIOLayerMethods.getsockname = PSMGetsockname;
nsSSLIOLayerMethods.getpeername = PSMGetpeername;
nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption;
nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption;
nsSSLIOLayerMethods.recv = PSMRecv;
nsSSLIOLayerMethods.send = PSMSend;
nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue;
nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect;
nsSSLIOLayerMethods.close = nsSSLIOLayerClose;
nsSSLIOLayerMethods.write = nsSSLIOLayerWrite;
nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll;
nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect;
nsSSLIOLayerMethods.close = nsSSLIOLayerClose;
nsSSLIOLayerMethods.write = nsSSLIOLayerWrite;
nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll;
}
mutex = PR_NewLock();
if (!mutex)

View File

@ -248,6 +248,7 @@ public:
static nsresult Init();
static void Cleanup();
static PRBool nsSSLIOLayerInitialized;
static PRDescIdentity nsSSLIOLayerIdentity;
static PRIOMethods nsSSLIOLayerMethods;

View File

@ -79,26 +79,6 @@
#include "nsSSLStatus.h"
#include "nsNSSIOLayer.h"
// We must ensure that the nsNSSComponent has been loaded before
// creating any other components.
static void EnsureNSSInitialized(PRBool triggeredByNSSComponent)
{
static PRBool haveLoaded = PR_FALSE;
if (haveLoaded)
return;
haveLoaded = PR_TRUE;
if (triggeredByNSSComponent) {
// We must prevent a recursion, as nsNSSComponent creates
// additional instances
return;
}
nsCOMPtr<nsISupports> nssComponent
= do_GetService(PSM_COMPONENT_CONTRACTID);
}
// These two macros are ripped off from nsIGenericFactory.h and slightly
// modified.
#define NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(triggeredByNSSComponent, \
@ -110,16 +90,27 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
nsresult rv; \
_InstanceClass * inst; \
\
EnsureNSSInitialized(triggeredByNSSComponent); \
\
*aResult = NULL; \
if (NULL != aOuter) { \
rv = NS_ERROR_NO_AGGREGATION; \
return rv; \
} \
\
if (triggeredByNSSComponent) \
{ \
if (!EnsureNSSInitialized(nssLoading)) \
return NS_ERROR_FAILURE; \
} \
else \
{ \
if (!EnsureNSSInitialized(nssEnsure)) \
return NS_ERROR_FAILURE; \
} \
\
NS_NEWXPCOM(inst, _InstanceClass); \
if (NULL == inst) { \
if (triggeredByNSSComponent) \
EnsureNSSInitialized(nssInitFailed); \
rv = NS_ERROR_OUT_OF_MEMORY; \
return rv; \
} \
@ -127,6 +118,14 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
rv = inst->QueryInterface(aIID, aResult); \
NS_RELEASE(inst); \
\
if (triggeredByNSSComponent) \
{ \
if (NS_SUCCEEDED(rv)) \
EnsureNSSInitialized(nssInitSucceeded); \
else \
EnsureNSSInitialized(nssInitFailed); \
} \
\
return rv; \
} \
@ -140,16 +139,27 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
nsresult rv; \
_InstanceClass * inst; \
\
EnsureNSSInitialized(triggeredByNSSComponent); \
\
*aResult = NULL; \
if (NULL != aOuter) { \
rv = NS_ERROR_NO_AGGREGATION; \
return rv; \
} \
\
if (triggeredByNSSComponent) \
{ \
if (!EnsureNSSInitialized(nssLoading)) \
return NS_ERROR_FAILURE; \
} \
else \
{ \
if (!EnsureNSSInitialized(nssEnsure)) \
return NS_ERROR_FAILURE; \
} \
\
NS_NEWXPCOM(inst, _InstanceClass); \
if (NULL == inst) { \
if (triggeredByNSSComponent) \
EnsureNSSInitialized(nssInitFailed); \
rv = NS_ERROR_OUT_OF_MEMORY; \
return rv; \
} \
@ -160,6 +170,14 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
} \
NS_RELEASE(inst); \
\
if (triggeredByNSSComponent) \
{ \
if (NS_SUCCEEDED(rv)) \
EnsureNSSInitialized(nssInitSucceeded); \
else \
EnsureNSSInitialized(nssInitFailed); \
} \
\
return rv; \
} \