mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
fixes crash in js_FreeStack caused by a race condition in necko. see 139556 for the details. r=rpotts, sr=darin
This commit is contained in:
parent
11c77022cb
commit
5f7d72f9e8
@ -49,6 +49,7 @@
|
|||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsIProxyObjectManager.h"
|
#include "nsIProxyObjectManager.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||||
|
|
||||||
@ -520,6 +521,10 @@ nsFileTransport::AsyncRead(nsIStreamListener *aListener,
|
|||||||
mTransferAmount = aTransferCount;
|
mTransferAmount = aTransferCount;
|
||||||
mXferState = OPEN_FOR_READ;
|
mXferState = OPEN_FOR_READ;
|
||||||
|
|
||||||
|
nsIEventQueueService* eqService = mService->GetCachedEventQueueService();
|
||||||
|
eqService->GetSpecialEventQueue(nsIEventQueueService::CURRENT_THREAD_EVENT_QUEUE, getter_AddRefs(mEventQ));
|
||||||
|
NS_ASSERTION(mEventQ, "No Event Queue on calling thread");
|
||||||
|
|
||||||
LOG(("nsFileTransport: AsyncRead [this=%x %s] mOffset=%d mTransferAmount=%d\n",
|
LOG(("nsFileTransport: AsyncRead [this=%x %s] mOffset=%d mTransferAmount=%d\n",
|
||||||
this, mStreamName.get(), mOffset, mTransferAmount));
|
this, mStreamName.get(), mOffset, mTransferAmount));
|
||||||
|
|
||||||
@ -563,6 +568,10 @@ nsFileTransport::AsyncWrite(nsIStreamProvider *aProvider,
|
|||||||
mTransferAmount = aTransferCount;
|
mTransferAmount = aTransferCount;
|
||||||
mXferState = OPEN_FOR_WRITE;
|
mXferState = OPEN_FOR_WRITE;
|
||||||
|
|
||||||
|
nsIEventQueueService* eqService = mService->GetCachedEventQueueService();
|
||||||
|
eqService->GetSpecialEventQueue(nsIEventQueueService::CURRENT_THREAD_EVENT_QUEUE, getter_AddRefs(mEventQ));
|
||||||
|
NS_ASSERTION(mEventQ, "No Event Queue on calling thread");
|
||||||
|
|
||||||
LOG(("nsFileTransport: AsyncWrite [this=%x %s] mOffset=%d mTransferAmount=%d\n",
|
LOG(("nsFileTransport: AsyncWrite [this=%x %s] mOffset=%d mTransferAmount=%d\n",
|
||||||
this, mStreamName.get(), mOffset, mTransferAmount));
|
this, mStreamName.get(), mOffset, mTransferAmount));
|
||||||
|
|
||||||
@ -823,27 +832,38 @@ nsFileTransport::Process(nsIProgressEventSink *progressSink)
|
|||||||
// is reusing the stream.
|
// is reusing the stream.
|
||||||
mXferState = CLOSING;
|
mXferState = CLOSING;
|
||||||
DoClose();
|
DoClose();
|
||||||
nsCOMPtr <nsISupports> saveContext = mContext;
|
|
||||||
nsCOMPtr <nsIStreamListener> saveListener = mListener;
|
|
||||||
mListener = nsnull;
|
|
||||||
mContext = nsnull;
|
|
||||||
|
|
||||||
// close the data source
|
// close the data source
|
||||||
NS_IF_RELEASE(mSourceWrapper);
|
NS_IF_RELEASE(mSourceWrapper);
|
||||||
mSourceWrapper = nsnull;
|
mSourceWrapper = nsnull;
|
||||||
|
|
||||||
if (progressSink) {
|
if (progressSink) {
|
||||||
progressSink->OnStatus(this, saveContext,
|
progressSink->OnStatus(this,
|
||||||
NS_NET_STATUS_READ_FROM,
|
mContext,
|
||||||
NS_ConvertASCIItoUCS2(mStreamName).get());
|
NS_NET_STATUS_READ_FROM,
|
||||||
|
NS_ConvertASCIItoUCS2(mStreamName).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (saveListener) {
|
if (mListener) {
|
||||||
saveListener->OnStopRequest(this, saveContext, mStatus);
|
mListener->OnStopRequest(this, mContext, mStatus);
|
||||||
saveListener = 0;
|
mListener = 0;
|
||||||
}
|
}
|
||||||
saveContext = 0;
|
|
||||||
|
|
||||||
|
// if we have a context, we have to ensure that it is released on the
|
||||||
|
// proper thread.
|
||||||
|
if (mContext) {
|
||||||
|
if (mEventQ) {
|
||||||
|
// see http://bugzilla.mozilla.org/show_bug.cgi?id=139556#c64
|
||||||
|
// for the reason behind this evil reference counting.
|
||||||
|
nsISupports* doomed = mContext.get();
|
||||||
|
NS_ADDREF(doomed);
|
||||||
|
mContext = 0;
|
||||||
|
NS_ProxyRelease(mEventQ, doomed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mContext = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,16 +1022,31 @@ nsFileTransport::Process(nsIProgressEventSink *progressSink)
|
|||||||
NS_IF_RELEASE(mSinkWrapper);
|
NS_IF_RELEASE(mSinkWrapper);
|
||||||
mSinkWrapper = nsnull;
|
mSinkWrapper = nsnull;
|
||||||
|
|
||||||
if (mProvider) {
|
|
||||||
mProvider->OnStopRequest(this, mContext, mStatus);
|
|
||||||
mProvider = 0;
|
|
||||||
}
|
|
||||||
if (progressSink)
|
if (progressSink)
|
||||||
progressSink->OnStatus(this, mContext,
|
progressSink->OnStatus(this, mContext,
|
||||||
NS_NET_STATUS_WROTE_TO,
|
NS_NET_STATUS_WROTE_TO,
|
||||||
NS_ConvertASCIItoUCS2(mStreamName).get());
|
NS_ConvertASCIItoUCS2(mStreamName).get());
|
||||||
mContext = 0;
|
|
||||||
|
|
||||||
|
if (mProvider) {
|
||||||
|
mProvider->OnStopRequest(this, mContext, mStatus);
|
||||||
|
mProvider = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have a context, we have to ensure that it is released on the
|
||||||
|
// proper thread.
|
||||||
|
if (mContext) {
|
||||||
|
if (mEventQ) {
|
||||||
|
// see http://bugzilla.mozilla.org/show_bug.cgi?id=139556#c64
|
||||||
|
// for the reason behind this evil reference counting.
|
||||||
|
nsISupports* doomed = mContext.get();
|
||||||
|
NS_ADDREF(doomed);
|
||||||
|
mContext = 0;
|
||||||
|
NS_ProxyRelease(mEventQ, doomed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mContext = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
mXferState = CLOSING;
|
mXferState = CLOSING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,9 @@ protected:
|
|||||||
|
|
||||||
nsCOMPtr<nsISupports> mContext;
|
nsCOMPtr<nsISupports> mContext;
|
||||||
|
|
||||||
|
// Queue where release of context, listener, and/or provider should occur.
|
||||||
|
nsCOMPtr<nsIEventQueue> mEventQ;
|
||||||
|
|
||||||
// mXferState is only changed by the file transport thread:
|
// mXferState is only changed by the file transport thread:
|
||||||
XferState mXferState;
|
XferState mXferState;
|
||||||
|
|
||||||
|
@ -122,6 +122,15 @@ nsFileTransportService::GetCachedMimeService()
|
|||||||
return mMimeService.get();
|
return mMimeService.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIEventQueueService*
|
||||||
|
nsFileTransportService::GetCachedEventQueueService()
|
||||||
|
{
|
||||||
|
if (!mEventQService) {
|
||||||
|
mEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID);
|
||||||
|
}
|
||||||
|
return mEventQService.get();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "nsIThreadPool.h"
|
#include "nsIThreadPool.h"
|
||||||
#include "nsSupportsArray.h"
|
#include "nsSupportsArray.h"
|
||||||
#include "nsIMIMEService.h"
|
#include "nsIMIMEService.h"
|
||||||
|
#include "nsIEventQueueService.h"
|
||||||
|
|
||||||
#define NS_FILE_TRANSPORT_WORKER_COUNT_MIN 1
|
#define NS_FILE_TRANSPORT_WORKER_COUNT_MIN 1
|
||||||
#define NS_FILE_TRANSPORT_WORKER_COUNT_MAX 4//16
|
#define NS_FILE_TRANSPORT_WORKER_COUNT_MAX 4//16
|
||||||
@ -64,6 +65,7 @@ public:
|
|||||||
static nsFileTransportService *GetInstance() { return mInstance; }
|
static nsFileTransportService *GetInstance() { return mInstance; }
|
||||||
|
|
||||||
nsIMIMEService* GetCachedMimeService();
|
nsIMIMEService* GetCachedMimeService();
|
||||||
|
nsIEventQueueService* GetCachedEventQueueService();
|
||||||
|
|
||||||
PRInt32 mConnectedTransports;
|
PRInt32 mConnectedTransports;
|
||||||
PRInt32 mTotalTransports;
|
PRInt32 mTotalTransports;
|
||||||
@ -79,6 +81,7 @@ protected:
|
|||||||
nsCOMPtr<nsIThreadPool> mPool;
|
nsCOMPtr<nsIThreadPool> mPool;
|
||||||
PRLock* mLock;
|
PRLock* mLock;
|
||||||
nsCOMPtr<nsIMIMEService> mMimeService;
|
nsCOMPtr<nsIMIMEService> mMimeService;
|
||||||
|
nsCOMPtr<nsIEventQueueService> mEventQService;
|
||||||
static nsFileTransportService* mInstance;
|
static nsFileTransportService* mInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include "nsITransportSecurityInfo.h"
|
#include "nsITransportSecurityInfo.h"
|
||||||
#include "nsMemory.h"
|
#include "nsMemory.h"
|
||||||
#include "nsIProxyInfo.h"
|
#include "nsIProxyInfo.h"
|
||||||
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
#if defined(PR_LOGGING)
|
#if defined(PR_LOGGING)
|
||||||
static PRLogModuleInfo *gSocketTransportLog = nsnull;
|
static PRLogModuleInfo *gSocketTransportLog = nsnull;
|
||||||
@ -2637,6 +2638,12 @@ nsSocketRequest::SetTransport(nsSocketTransport *aTransport)
|
|||||||
//
|
//
|
||||||
NS_IF_RELEASE(mTransport);
|
NS_IF_RELEASE(mTransport);
|
||||||
NS_IF_ADDREF(mTransport = aTransport);
|
NS_IF_ADDREF(mTransport = aTransport);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set the event queue
|
||||||
|
//
|
||||||
|
nsIEventQueueService* eqService = aTransport->mService->GetCachedEventQueueService();
|
||||||
|
eqService->GetSpecialEventQueue(nsIEventQueueService::CURRENT_THREAD_EVENT_QUEUE, getter_AddRefs(mEventQ));
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -2657,9 +2664,21 @@ nsSocketRequest::OnStop()
|
|||||||
mObserver->OnStartRequest(this, mContext);
|
mObserver->OnStartRequest(this, mContext);
|
||||||
mStartFired = PR_TRUE;
|
mStartFired = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mObserver->OnStopRequest(this, mContext, mStatus);
|
mObserver->OnStopRequest(this, mContext, mStatus);
|
||||||
mObserver = 0;
|
mObserver = 0;
|
||||||
mContext = 0;
|
|
||||||
|
if (mContext) {
|
||||||
|
if (mEventQ) {
|
||||||
|
nsISupports* doomed = mContext.get();
|
||||||
|
NS_ADDREF(doomed);
|
||||||
|
mContext = 0;
|
||||||
|
NS_ProxyRelease(mEventQ, doomed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mContext = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
mStopFired = PR_TRUE;
|
mStopFired = PR_TRUE;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -309,6 +309,8 @@ protected:
|
|||||||
nsSocketBOS *mBOS; // weak reference
|
nsSocketBOS *mBOS; // weak reference
|
||||||
nsSocketReadRequest *mReadRequest;
|
nsSocketReadRequest *mReadRequest;
|
||||||
nsSocketWriteRequest *mWriteRequest;
|
nsSocketWriteRequest *mWriteRequest;
|
||||||
|
|
||||||
|
friend nsSocketRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,6 +455,8 @@ protected:
|
|||||||
nsSocketTransport *mTransport;
|
nsSocketTransport *mTransport;
|
||||||
nsCOMPtr<nsIRequestObserver> mObserver;
|
nsCOMPtr<nsIRequestObserver> mObserver;
|
||||||
nsCOMPtr<nsISupports> mContext;
|
nsCOMPtr<nsISupports> mContext;
|
||||||
|
// Queue where release of context, listener, and/or provider should occur.
|
||||||
|
nsCOMPtr<nsIEventQueue> mEventQ;
|
||||||
nsresult mStatus;
|
nsresult mStatus;
|
||||||
PRIntn mSuspendCount;
|
PRIntn mSuspendCount;
|
||||||
PRPackedBool mCanceled;
|
PRPackedBool mCanceled;
|
||||||
|
@ -211,6 +211,15 @@ nsSocketTransportService::Init(void)
|
|||||||
rv = NS_ERROR_UNEXPECTED;
|
rv = NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv) && !mEventQService) {
|
||||||
|
mEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID);
|
||||||
|
if (!mEventQService) {
|
||||||
|
rv = NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,22 +800,22 @@ nsSocketTransportService::GetNeckoStringByName (const char *aName, PRUnichar **a
|
|||||||
nsresult res;
|
nsresult res;
|
||||||
nsAutoString resultString; resultString.AssignWithConversion(aName);
|
nsAutoString resultString; resultString.AssignWithConversion(aName);
|
||||||
|
|
||||||
if (!m_stringBundle) {
|
if (!mStringBundle) {
|
||||||
const char propertyURL[] = NECKO_MSGS_URL;
|
const char propertyURL[] = NECKO_MSGS_URL;
|
||||||
// make sure that we get this service on the UI thread.
|
// make sure that we get this service on the UI thread.
|
||||||
NS_WITH_PROXIED_SERVICE(nsIStringBundleService, sBundleService, kStringBundleServiceCID,
|
NS_WITH_PROXIED_SERVICE(nsIStringBundleService, sBundleService, kStringBundleServiceCID,
|
||||||
NS_UI_THREAD_EVENTQ, &res);
|
NS_UI_THREAD_EVENTQ, &res);
|
||||||
if (NS_SUCCEEDED (res) && (nsnull != sBundleService)) {
|
if (NS_SUCCEEDED (res) && (nsnull != sBundleService)) {
|
||||||
res = sBundleService->CreateBundle(propertyURL, getter_AddRefs(m_stringBundle));
|
res = sBundleService->CreateBundle(propertyURL, getter_AddRefs(mStringBundle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_stringBundle)
|
if (mStringBundle)
|
||||||
{
|
{
|
||||||
nsAutoString unicodeName; unicodeName.AssignWithConversion(aName);
|
nsAutoString unicodeName; unicodeName.AssignWithConversion(aName);
|
||||||
|
|
||||||
PRUnichar *ptrv = nsnull;
|
PRUnichar *ptrv = nsnull;
|
||||||
res = m_stringBundle->GetStringFromName(unicodeName.get(), &ptrv);
|
res = mStringBundle->GetStringFromName(unicodeName.get(), &ptrv);
|
||||||
|
|
||||||
if (NS_FAILED(res))
|
if (NS_FAILED(res))
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
#include "nsIDNSService.h"
|
#include "nsIDNSService.h"
|
||||||
|
#include "nsIEventQueueService.h"
|
||||||
|
|
||||||
#if defined(XP_PC) || defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_MAC)
|
#if defined(XP_PC) || defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_MAC)
|
||||||
//
|
//
|
||||||
@ -99,6 +100,7 @@ public:
|
|||||||
nsresult GetNeckoStringByName (const char *aName, PRUnichar **aString);
|
nsresult GetNeckoStringByName (const char *aName, PRUnichar **aString);
|
||||||
|
|
||||||
nsIDNSService* GetCachedDNSService() { return mDNSService.get(); }
|
nsIDNSService* GetCachedDNSService() { return mDNSService.get(); }
|
||||||
|
nsIEventQueueService* GetCachedEventQueueService() { return mEventQService.get(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsIThread* mThread;
|
nsIThread* mThread;
|
||||||
@ -111,8 +113,9 @@ protected:
|
|||||||
PRInt32 mSelectFDSetCount;
|
PRInt32 mSelectFDSetCount;
|
||||||
PRPollDesc* mSelectFDSet;
|
PRPollDesc* mSelectFDSet;
|
||||||
nsSocketTransport** mActiveTransportList;
|
nsSocketTransport** mActiveTransportList;
|
||||||
nsCOMPtr<nsIStringBundle> m_stringBundle;
|
nsCOMPtr<nsIStringBundle> mStringBundle;
|
||||||
nsCOMPtr<nsIDNSService> mDNSService;
|
nsCOMPtr<nsIDNSService> mDNSService;
|
||||||
|
nsCOMPtr<nsIEventQueueService> mEventQService;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1026,6 +1026,15 @@ nsDNSService::Init()
|
|||||||
rv = InstallPrefObserver();
|
rv = InstallPrefObserver();
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// install xpcom shutdown observer
|
||||||
|
nsCOMPtr<nsIObserverService> observerService =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
|
||||||
mState = DNS_ONLINE;
|
mState = DNS_ONLINE;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
@ -1265,6 +1274,13 @@ nsDNSService::Observe(nsISupports * subject,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
if (!nsCRT::strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, topic))
|
||||||
|
{
|
||||||
|
// we need to shutdown!
|
||||||
|
ShutdownInternal();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, topic))
|
if (nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, topic))
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
@ -1302,7 +1318,6 @@ nsDNSService::Observe(nsISupports * subject,
|
|||||||
mIDNConverter = nsnull;
|
mIDNConverter = nsnull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1829,6 +1844,15 @@ nsDNSService::ShutdownInternal()
|
|||||||
|
|
||||||
(void) RemovePrefObserver();
|
(void) RemovePrefObserver();
|
||||||
|
|
||||||
|
|
||||||
|
// remove xpcom shutdown observer
|
||||||
|
nsCOMPtr<nsIObserverService> observerService =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// reset hashtable
|
// reset hashtable
|
||||||
// XXX assert hashtable is empty
|
// XXX assert hashtable is empty
|
||||||
PL_DHashTableFinish(&mHashTable);
|
PL_DHashTableFinish(&mHashTable);
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
nsProxyEvent.h
|
nsProxyEvent.h
|
||||||
|
nsProxyRelease.h
|
||||||
nsProxiedService.h
|
nsProxiedService.h
|
||||||
|
@ -35,6 +35,7 @@ endif
|
|||||||
|
|
||||||
EXPORTS = \
|
EXPORTS = \
|
||||||
nsProxyEvent.h \
|
nsProxyEvent.h \
|
||||||
|
nsProxyRelease.h \
|
||||||
nsProxiedService.h \
|
nsProxiedService.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ MODULE=xpcom
|
|||||||
|
|
||||||
EXPORTS = \
|
EXPORTS = \
|
||||||
nsProxyEvent.h \
|
nsProxyEvent.h \
|
||||||
|
nsProxyRelease.h \
|
||||||
nsProxiedService.h \
|
nsProxiedService.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ static void* PR_CALLBACK
|
|||||||
ReleaseDestructorEventHandler(PLEvent *self)
|
ReleaseDestructorEventHandler(PLEvent *self)
|
||||||
{
|
{
|
||||||
nsISupports* owner = (nsISupports*) PL_GetEventOwner(self);
|
nsISupports* owner = (nsISupports*) PL_GetEventOwner(self);
|
||||||
NS_DELETEXPCOM(owner);
|
NS_RELEASE(owner);
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +60,44 @@ ReleaseDestructorDestroyHandler(PLEvent *self)
|
|||||||
PR_DELETE(self);
|
PR_DELETE(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
NS_ProxyRelease(nsIEventQueue *eventQ, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE)
|
||||||
|
{
|
||||||
|
if (!doomed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!eventQ) {
|
||||||
|
NS_RELEASE(doomed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alwaysProxy) {
|
||||||
|
PRBool onCurrentThread = PR_FALSE;
|
||||||
|
eventQ->IsQueueOnCurrentThread(&onCurrentThread);
|
||||||
|
if (onCurrentThread) {
|
||||||
|
NS_RELEASE(doomed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PLEvent *ev = new PLEvent;
|
||||||
|
if (!ev) {
|
||||||
|
NS_ERROR("failed to allocate PLEvent");
|
||||||
|
// we do not release doomed here since it may cause a delete on the the
|
||||||
|
// wrong thread. better to leak than crash.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PL_InitEvent(ev,
|
||||||
|
(void *) doomed,
|
||||||
|
ReleaseDestructorEventHandler,
|
||||||
|
ReleaseDestructorDestroyHandler);
|
||||||
|
|
||||||
|
PRStatus rv = eventQ->PostEvent(ev);
|
||||||
|
NS_ASSERTION(rv == PR_SUCCESS, "PostEvent failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define NS_IMPL_PROXY_RELEASE(_class) \
|
#define NS_IMPL_PROXY_RELEASE(_class) \
|
||||||
NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
|
NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
|
||||||
{ \
|
{ \
|
||||||
@ -106,5 +144,7 @@ NS_IMETHODIMP_(nsrefcnt) _class::Release(void)
|
|||||||
return count; \
|
return count; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user