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-18 14:31:31 +01:00
parent 312b077424
commit bf083a3640
5 changed files with 127 additions and 68 deletions

View File

@ -275,8 +275,34 @@ nsTokenEventRunnable::Run()
return nssComponent->DispatchEvent(mType, mTokenName); return nssComponent->DispatchEvent(mType, mTokenName);
} }
// We must ensure that the nsNSSComponent has been loaded before
// creating any other components.
PRBool EnsureNSSInitialized(PRBool ensure)
{
static PRBool haveLoaded = PR_FALSE;
if (!ensure) {
haveLoaded = PR_FALSE;
return PR_FALSE;
}
if (haveLoaded)
return PR_TRUE;
nsCOMPtr<nsISupports> nssComponent
= do_GetService(PSM_COMPONENT_CONTRACTID);
// If we succeeded to get the PSM service rise the flag to avoid
// unnecessary calls to GetService.
if (nssComponent)
haveLoaded = PR_TRUE;
return haveLoaded;
}
nsNSSComponent::nsNSSComponent() nsNSSComponent::nsNSSComponent()
:mNSSInitialized(PR_FALSE), mThreadList(nsnull) :mNSSInitialized(PR_FALSE), mThreadList(nsnull),
mSSLThread(NULL), mCertVerificationThread(NULL)
{ {
mutex = PR_NewLock(); mutex = PR_NewLock();
@ -296,19 +322,11 @@ nsNSSComponent::nsNSSComponent()
// registering all identity data until first needed. // registering all identity data until first needed.
memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType)); memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
nsSSLIOLayerHelpers::Init();
NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!"); NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
++mInstanceCount; ++mInstanceCount;
hashTableCerts = nsnull; hashTableCerts = nsnull;
mShutdownObjectList = nsNSSShutDownList::construct(); mShutdownObjectList = nsNSSShutDownList::construct();
mIsNetworkDown = PR_FALSE; mIsNetworkDown = PR_FALSE;
mSSLThread = new nsSSLThread();
if (mSSLThread)
mSSLThread->startThread();
mCertVerificationThread = new nsCertVerificationThread();
if (mCertVerificationThread)
mCertVerificationThread->startThread();
} }
nsNSSComponent::~nsNSSComponent() nsNSSComponent::~nsNSSComponent()
@ -357,6 +375,8 @@ nsNSSComponent::~nsNSSComponent()
mutex = nsnull; mutex = nsnull;
} }
EnsureNSSInitialized(PR_FALSE);
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n")); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
} }
@ -1470,9 +1490,6 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
certHashtable_valueCompare, 0, 0 );
nsresult rv; nsresult rv;
nsCAutoString profileStr; nsCAutoString profileStr;
nsCOMPtr<nsIFile> profilePath; nsCOMPtr<nsIFile> profilePath;
@ -1521,6 +1538,9 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
certHashtable_valueCompare, 0, 0 );
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
// function may modify the parameters // function may modify the parameters
// ignore return code from conversion, we continue anyway // ignore return code from conversion, we continue anyway
@ -1710,8 +1730,7 @@ nsNSSComponent::Init()
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n")); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
if (!mutex || !mShutdownObjectList || if (!mutex || !mShutdownObjectList)
!mSSLThread || !mCertVerificationThread)
{ {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n")); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n"));
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -1747,9 +1766,30 @@ nsNSSComponent::Init()
rv = InitializeNSS(PR_TRUE); // ok to show a warning box on failure rv = InitializeNSS(PR_TRUE); // ok to show a warning box on failure
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n")); PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
DeregisterObservers();
mPIPNSSBundle = nsnull;
return rv; 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(); InitializeCRLUpdateTimer();
RegisterPSMContentListener(); RegisterPSMContentListener();
@ -2186,6 +2226,31 @@ nsNSSComponent::RegisterObservers()
return NS_OK; 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 NS_IMETHODIMP
nsNSSComponent::RememberCert(CERTCertificate *cert) nsNSSComponent::RememberCert(CERTCertificate *cert)
{ {

View File

@ -93,6 +93,8 @@
#define NS_CRYPTO_HMAC_CLASSNAME "Mozilla Crypto HMAC Function Component" #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}} #define NS_CRYPTO_HMAC_CID {0xa496d0a2, 0xdff7, 0x4e23, {0xbd, 0x65, 0x1c, 0xa7, 0x42, 0xfa, 0x17, 0x8a}}
extern PRBool EnsureNSSInitialized(PRBool reset);
//-------------------------------------------- //--------------------------------------------
// Now we need a content listener to register // Now we need a content listener to register
//-------------------------------------------- //--------------------------------------------
@ -287,6 +289,7 @@ private:
nsresult ConfigureInternalPKCS11Token(); nsresult ConfigureInternalPKCS11Token();
nsresult RegisterPSMContentListener(); nsresult RegisterPSMContentListener();
nsresult RegisterObservers(); nsresult RegisterObservers();
nsresult DeregisterObservers();
nsresult DownloadCrlSilently(); nsresult DownloadCrlSilently();
nsresult PostCRLImportEvent(const nsCSubstring &urlString, nsIStreamListener *psmDownloader); nsresult PostCRLImportEvent(const nsCSubstring &urlString, nsIStreamListener *psmDownloader);
nsresult getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key); nsresult getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key);

View File

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

View File

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

View File

@ -79,26 +79,6 @@
#include "nsSSLStatus.h" #include "nsSSLStatus.h"
#include "nsNSSIOLayer.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 // These two macros are ripped off from nsIGenericFactory.h and slightly
// modified. // modified.
#define NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(triggeredByNSSComponent, \ #define NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(triggeredByNSSComponent, \
@ -110,7 +90,9 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
nsresult rv; \ nsresult rv; \
_InstanceClass * inst; \ _InstanceClass * inst; \
\ \
EnsureNSSInitialized(triggeredByNSSComponent); \ if (!triggeredByNSSComponent && \
!EnsureNSSInitialized(PR_TRUE)) \
return NS_ERROR_FAILURE; \
\ \
*aResult = NULL; \ *aResult = NULL; \
if (NULL != aOuter) { \ if (NULL != aOuter) { \
@ -140,7 +122,9 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
nsresult rv; \ nsresult rv; \
_InstanceClass * inst; \ _InstanceClass * inst; \
\ \
EnsureNSSInitialized(triggeredByNSSComponent); \ if (!triggeredByNSSComponent && \
!EnsureNSSInitialized(PR_TRUE)) \
return NS_ERROR_FAILURE; \
\ \
*aResult = NULL; \ *aResult = NULL; \
if (NULL != aOuter) { \ if (NULL != aOuter) { \