Bug 404870. Avoid read access to mThread racing with setting mThread to null (which could crash). Also, detect when the thread is no longer accepting events and treat it as the thread not being there anymore in nsSocketTransportService::Dispatch.

This commit is contained in:
roc+@cs.cmu.edu 2007-12-04 18:18:58 -08:00
Родитель 16fb24b0d4
Коммит f840924682
2 изменённых файлов: 39 добавлений и 7 удалений

Просмотреть файл

@ -97,20 +97,37 @@ nsSocketTransportService::~nsSocketTransportService()
//-----------------------------------------------------------------------------
// event queue (any thread)
already_AddRefed<nsIThread>
nsSocketTransportService::GetThreadSafely()
{
nsAutoLock lock(mLock);
nsIThread* result = mThread;
NS_IF_ADDREF(result);
return result;
}
NS_IMETHODIMP
nsSocketTransportService::Dispatch(nsIRunnable *event, PRUint32 flags)
{
LOG(("STS dispatch [%p]\n", event));
NS_ENSURE_TRUE(mThread, NS_ERROR_NOT_INITIALIZED);
return mThread->Dispatch(event, flags);
nsCOMPtr<nsIThread> thread = GetThreadSafely();
NS_ENSURE_TRUE(thread, NS_ERROR_NOT_INITIALIZED);
nsresult rv = thread->Dispatch(event, flags);
if (rv == NS_ERROR_UNEXPECTED) {
// Thread is no longer accepting events. We must have just shut it
// down on the main thread. Pretend we never saw it.
rv = NS_ERROR_NOT_INITIALIZED;
}
return rv;
}
NS_IMETHODIMP
nsSocketTransportService::IsOnCurrentThread(PRBool *result)
{
NS_ENSURE_TRUE(mThread, NS_ERROR_NOT_INITIALIZED);
return mThread->IsOnCurrentThread(result);
nsCOMPtr<nsIThread> thread = GetThreadSafely();
NS_ENSURE_TRUE(thread, NS_ERROR_NOT_INITIALIZED);
return thread->IsOnCurrentThread(result);
}
//-----------------------------------------------------------------------------
@ -382,8 +399,15 @@ nsSocketTransportService::Init()
}
}
nsresult rv = NS_NewThread(&mThread, this);
nsCOMPtr<nsIThread> thread;
nsresult rv = NS_NewThread(getter_AddRefs(thread), this);
if (NS_FAILED(rv)) return rv;
{
nsAutoLock lock(mLock);
// Install our mThread, protecting against concurrent readers
thread.swap(mThread);
}
mInitialized = PR_TRUE;
return NS_OK;
@ -416,7 +440,12 @@ nsSocketTransportService::Shutdown()
// join with thread
mThread->Shutdown();
NS_RELEASE(mThread);
{
nsAutoLock lock(mLock);
// Drop our reference to mThread and make sure that any concurrent
// readers are excluded
mThread = nsnull;
}
mInitialized = PR_FALSE;
mShuttingDown = PR_FALSE;

Просмотреть файл

@ -178,7 +178,7 @@ private:
// misc (any thread)
//-------------------------------------------------------------------------
nsIThread *mThread;
nsCOMPtr<nsIThread> mThread; // protected by mLock
PRFileDesc *mThreadEvent;
// protected by mLock. mThreadEvent may change
// if the old pollable event is broken. only
@ -190,6 +190,9 @@ private:
PRBool mAutodialEnabled;
// pref to control autodial code
// Returns mThread, protecting the get-and-addref with mLock
already_AddRefed<nsIThread> GetThreadSafely();
//-------------------------------------------------------------------------
// initialization and shutdown (any thread)
//-------------------------------------------------------------------------