зеркало из https://github.com/mozilla/pjs.git
Fix IMAP deadlock when the network becomes unreachable (bug 410747), patch=Emre Birol <bugmil.ebirol@gmail.com>, r=bienvenu, sr=dmose, a=blocking-3.0a1+
This commit is contained in:
Родитель
c5ad605034
Коммит
dd2c44c1e9
|
@ -54,6 +54,7 @@ XPIDLSRCS = \
|
|||
nsIImapService.idl \
|
||||
nsIImapServerSink.idl \
|
||||
nsIImapMessageSink.idl \
|
||||
nsIImapProtocolSink.idl \
|
||||
nsIImapIncomingServer.idl \
|
||||
nsIImapFlagAndUidState.idl \
|
||||
nsIImapMockChannel.idl \
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Messaging, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Emre Birol <ebirol@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Helper interface that contains operations MUST be proxied
|
||||
* over UI thread.
|
||||
*/
|
||||
[scriptable, uuid(72187a30-dad7-4800-b989-adfcbdc9a650)]
|
||||
interface nsIImapProtocolSink : nsISupports {
|
||||
|
||||
/**
|
||||
* Does general cleanup for the imap protocol object.
|
||||
*/
|
||||
void closeStreams();
|
||||
};
|
|
@ -108,6 +108,7 @@ PRLogModuleInfo *IMAP;
|
|||
#include "nsIProxyInfo.h"
|
||||
#include "nsISSLSocketControl.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#define ONE_SECOND ((PRUint32)1000) // one second
|
||||
|
||||
|
@ -300,6 +301,7 @@ NS_INTERFACE_MAP_BEGIN(nsImapProtocol)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIImapProtocol)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIImapProtocolSink)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
|
||||
static PRInt32 gTooFastTime = 2;
|
||||
|
@ -630,6 +632,17 @@ nsImapProtocol::SetupSinkProxy()
|
|||
getter_AddRefs(m_imapServerSink));
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "couldn't get proxies");
|
||||
}
|
||||
if (!m_imapProtocolSink)
|
||||
{
|
||||
nsCOMPtr<nsIImapProtocolSink> anImapProxyHelper(do_QueryInterface(NS_ISUPPORTS_CAST(nsIImapProtocolSink*, this), &res));
|
||||
if (NS_SUCCEEDED(res) && anImapProxyHelper)
|
||||
res = proxyManager->GetProxyForObject( m_sinkEventTarget,
|
||||
NS_GET_IID(nsIImapProtocolSink),
|
||||
anImapProxyHelper,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(m_imapProtocolSink));
|
||||
NS_ASSERTION(NS_SUCCEEDED(res), "couldn't get proxies");
|
||||
}
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(PR_FALSE, "can't get proxy service");
|
||||
|
@ -946,30 +959,30 @@ private:
|
|||
|
||||
NS_IMETHODIMP nsImapProtocol::Run()
|
||||
{
|
||||
nsImapProtocol *me = this;
|
||||
NS_ASSERTION(me, "Yuk, me is null.\n");
|
||||
|
||||
PR_CEnterMonitor(this);
|
||||
NS_ASSERTION(me->m_imapThreadIsRunning == PR_FALSE,
|
||||
NS_ASSERTION(m_imapThreadIsRunning == PR_FALSE,
|
||||
"Oh. oh. thread is already running. What's wrong here?");
|
||||
if (me->m_imapThreadIsRunning)
|
||||
if (m_imapThreadIsRunning)
|
||||
{
|
||||
PR_CExitMonitor(me);
|
||||
PR_CExitMonitor(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
me->m_imapThreadIsRunning = PR_TRUE;
|
||||
PR_CExitMonitor(me);
|
||||
m_imapThreadIsRunning = PR_TRUE;
|
||||
PR_CExitMonitor(this);
|
||||
|
||||
// call the platform specific main loop ....
|
||||
me->ImapThreadMainLoop();
|
||||
ImapThreadMainLoop();
|
||||
|
||||
|
||||
me->m_runningUrl = nsnull;
|
||||
CloseStreams();
|
||||
me->m_sinkEventTarget = nsnull;
|
||||
me->m_imapMailFolderSink = nsnull;
|
||||
me->m_imapMessageSink = nsnull;
|
||||
m_runningUrl = nsnull;
|
||||
|
||||
// close streams via UI thread if it's not already done
|
||||
if (m_imapProtocolSink)
|
||||
m_imapProtocolSink->CloseStreams();
|
||||
|
||||
m_sinkEventTarget = nsnull;
|
||||
m_imapMailFolderSink = nsnull;
|
||||
m_imapMessageSink = nsnull;
|
||||
|
||||
// shutdown this thread, but do it from the main thread
|
||||
nsCOMPtr<nsIRunnable> ev = new nsImapThreadShutdownEvent(m_iThread);
|
||||
|
@ -979,11 +992,14 @@ NS_IMETHODIMP nsImapProtocol::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// called from UI thread.
|
||||
// XXXbz except this is called from TellThreadToDie, which can get called on
|
||||
// either the UI thread or the IMAP protocol thread, per comments.
|
||||
void nsImapProtocol::CloseStreams()
|
||||
//
|
||||
// Must be called from UI thread only
|
||||
//
|
||||
NS_IMETHODIMP nsImapProtocol::CloseStreams()
|
||||
{
|
||||
// make sure that it is called by the UI thread
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "CloseStreams() should not be called from an off UI thread");
|
||||
|
||||
PR_CEnterMonitor(this);
|
||||
if (m_transport)
|
||||
{
|
||||
|
@ -994,15 +1010,11 @@ void nsImapProtocol::CloseStreams()
|
|||
}
|
||||
m_inputStream = nsnull;
|
||||
m_outputStream = nsnull;
|
||||
// XXXbz given that this can get called from off the UI thread, does the
|
||||
// release of m_channelListener need to be proxied?
|
||||
m_channelListener = nsnull;
|
||||
m_channelContext = nsnull;
|
||||
if (m_mockChannel)
|
||||
{
|
||||
m_mockChannel->Close();
|
||||
// XXXbz given that this can get called from off the UI thread, does the
|
||||
// release of m_mockChannel need to be proxied?
|
||||
m_mockChannel = nsnull;
|
||||
}
|
||||
m_channelInputStream = nsnull;
|
||||
|
@ -1024,6 +1036,7 @@ void nsImapProtocol::CloseStreams()
|
|||
me_server = nsnull;
|
||||
}
|
||||
m_server = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1089,7 +1102,12 @@ nsImapProtocol::TellThreadToDie(PRBool isSafeToClose)
|
|||
Logout(PR_TRUE, connectionIdle);
|
||||
}
|
||||
}
|
||||
CloseStreams();
|
||||
// close streams via UI thread
|
||||
if (m_imapProtocolSink)
|
||||
{
|
||||
m_imapProtocolSink->CloseStreams();
|
||||
m_imapProtocolSink = nsnull;
|
||||
}
|
||||
Log("TellThreadToDie", nsnull, "close socket connection");
|
||||
|
||||
PR_EnterMonitor(m_threadDeathMonitor);
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
#include "nsIImapServerSink.h"
|
||||
#include "nsIImapMessageSink.h"
|
||||
|
||||
// UI Thread proxy helper
|
||||
#include "nsIImapProtocolSink.h"
|
||||
|
||||
#include "nsImapServerResponseParser.h"
|
||||
#include "nsImapFlagAndUidState.h"
|
||||
#include "nsIMAPNamespace.h"
|
||||
|
@ -150,7 +153,7 @@ public:
|
|||
#define IMAP_ISSUED_LANGUAGE_REQUEST 0x00000020 // make sure we only issue the language request once per connection...
|
||||
|
||||
class nsImapProtocol : public nsIImapProtocol, public nsIRunnable, public nsIInputStreamCallback,
|
||||
public nsSupportsWeakReference, public nsMsgProtocol
|
||||
public nsSupportsWeakReference, public nsMsgProtocol, public nsIImapProtocolSink
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -170,8 +173,11 @@ public:
|
|||
//////////////////////////////////////////////////////////////////////////////////
|
||||
NS_DECL_NSIIMAPPROTOCOL
|
||||
|
||||
void CloseStreams();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// we support the nsIImapProtocolSink interface
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
NS_DECL_NSIIMAPPROTOCOLSINK
|
||||
|
||||
// message id string utilities.
|
||||
PRUint32 CountMessagesInIdString(const char *idString);
|
||||
static PRBool HandlingMultipleMessages(const nsCString &messageIdString);
|
||||
|
@ -372,6 +378,7 @@ private:
|
|||
nsCOMPtr<nsIImapMailFolderSink> m_imapMailFolderSink;
|
||||
nsCOMPtr<nsIImapMessageSink> m_imapMessageSink;
|
||||
nsCOMPtr<nsIImapServerSink> m_imapServerSink;
|
||||
nsCOMPtr<nsIImapProtocolSink> m_imapProtocolSink;
|
||||
|
||||
// helper function to setup imap sink interface proxies
|
||||
void SetupSinkProxy();
|
||||
|
|
Загрузка…
Ссылка в новой задаче