thunderbird/mozilla-1158578-recursion-fix.patch

148 lines
5.0 KiB
Diff

# vim: se ft=diff :
# HG changeset patch
# User Jan Horak <jhorak>
# Date 2017-04-26 02:36
# Parent 540cd06b1aea0bfa6f906b86393f5480914c01c2
Bug 1158578 - fix crash when compacting IMAP account. r=jorgk
diff --git a/mailnews/base/src/nsMsgFolderCompactor.cpp b/mailnews/base/src/nsMsgFolderCompactor.cpp
--- a/mailnews/base/src/nsMsgFolderCompactor.cpp
+++ b/mailnews/base/src/nsMsgFolderCompactor.cpp
@@ -31,16 +31,17 @@
#include "nsIMsgStatusFeedback.h"
#include "nsMsgBaseCID.h"
#include "nsIMsgFolderNotificationService.h"
#include "nsIMsgPluggableStore.h"
#include "nsMsgFolderCompactor.h"
#include <algorithm>
#include "nsIOutputStream.h"
#include "nsIInputStream.h"
+#include "nsPrintfCString.h"
//////////////////////////////////////////////////////////////////////////////
// nsFolderCompactState
//////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS(nsFolderCompactState, nsIMsgFolderCompactor, nsIRequestObserver, nsIStreamListener, nsICopyMessageStreamListener, nsIUrlListener)
@@ -1096,16 +1097,24 @@ nsOfflineStoreCompactState::OnStopReques
// check for it specifically and don't terminate the compaction.
if (NS_FAILED(rv) && rv != NS_MSG_ERROR_MSG_NOT_OFFLINE)
goto done;
uri = do_QueryInterface(ctxt, &rv);
if (NS_FAILED(rv)) goto done;
rv = GetMessage(getter_AddRefs(msgHdr));
if (NS_FAILED(rv)) goto done;
+ // This is however an unexpected condition, so let's print a warning.
+ if (rv == NS_MSG_ERROR_MSG_NOT_OFFLINE) {
+ nsAutoCString spec;
+ uri->GetSpec(spec);
+ nsPrintfCString msg("Message expectedly not available offline: %s", spec.get());
+ NS_WARNING(msg.get());
+ }
+
if (msgHdr)
{
if (NS_SUCCEEDED(status))
{
msgHdr->SetMessageOffset(m_startOfNewMsg);
char storeToken[100];
PR_snprintf(storeToken, sizeof(storeToken), "%lld", m_startOfNewMsg);
msgHdr->SetStringProperty("storeToken", storeToken);
diff --git a/mailnews/imap/src/nsImapProtocol.cpp b/mailnews/imap/src/nsImapProtocol.cpp
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -9500,35 +9500,66 @@ nsresult nsImapMockChannel::ReadFromMemC
// Content is modified so return an error so we try to open it the
// old fashioned way.
rv = NS_ERROR_FAILURE;
}
return rv;
}
+class nsReadFromImapConnectionFailure : public mozilla::Runnable
+{
+public:
+ nsReadFromImapConnectionFailure(nsImapMockChannel *aChannel)
+ : mImapMockChannel(aChannel)
+ {}
+
+ NS_IMETHOD Run()
+ {
+ if (mImapMockChannel) {
+ mImapMockChannel->RunOnStopRequestFailure();
+ }
+ return NS_OK;
+ }
+private:
+ RefPtr<nsImapMockChannel> mImapMockChannel;
+};
+
+
+nsresult nsImapMockChannel::RunOnStopRequestFailure()
+{
+ if (m_channelListener) {
+ m_channelListener->OnStopRequest(this, m_channelContext,
+ NS_MSG_ERROR_MSG_NOT_OFFLINE);
+ }
+ return NS_OK;
+}
+
// the requested url isn't in any of our caches so create an imap connection
// to process it.
nsresult nsImapMockChannel::ReadFromImapConnection()
{
nsresult rv = NS_OK;
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url);
bool localOnly = false;
imapUrl->GetLocalFetchOnly(&localOnly);
if (localOnly)
{
// This will cause an OnStartRunningUrl, and the subsequent close
// will then cause an OnStopRunningUrl with the cancel status.
NotifyStartEndReadFromCache(true);
Cancel(NS_MSG_ERROR_MSG_NOT_OFFLINE);
- if (m_channelListener)
- m_channelListener->OnStopRequest(this, m_channelContext,
- NS_MSG_ERROR_MSG_NOT_OFFLINE);
+
+ // Dispatch error notification, so ReadFromImapConnection() returns *before*
+ // the error is sent to the listener's OnStopRequest(). This avoids
+ // endless recursion where the caller relies on async execution.
+ nsCOMPtr<nsIRunnable> event = new nsReadFromImapConnectionFailure(this);
+ NS_DispatchToCurrentThread(event);
return NS_MSG_ERROR_MSG_NOT_OFFLINE;
}
nsCOMPtr <nsILoadGroup> loadGroup;
GetLoadGroup(getter_AddRefs(loadGroup));
if (!loadGroup) // if we don't have one, the url will snag one from the msg window...
mailnewsUrl->GetLoadGroup(getter_AddRefs(loadGroup));
diff --git a/mailnews/imap/src/nsImapProtocol.h b/mailnews/imap/src/nsImapProtocol.h
--- a/mailnews/imap/src/nsImapProtocol.h
+++ b/mailnews/imap/src/nsImapProtocol.h
@@ -714,16 +714,17 @@ public:
NS_DECL_NSIIMAPMOCKCHANNEL
NS_DECL_NSICHANNEL
NS_DECL_NSIREQUEST
NS_DECL_NSICACHEENTRYOPENCALLBACK
NS_DECL_NSITRANSPORTEVENTSINK
nsImapMockChannel();
static nsresult Create (const nsIID& iid, void **result);
+ nsresult RunOnStopRequestFailure();
protected:
virtual ~nsImapMockChannel();
nsCOMPtr <nsIURI> m_url;
nsCOMPtr<nsIURI> m_originalUrl;
nsCOMPtr<nsILoadGroup> m_loadGroup;
nsCOMPtr<nsILoadInfo> m_loadInfo;