bug 657076 - better error handling in FTP for e10s. r=jduell
authorNick Hurley <hurley@mozilla.com>
Tue, 10 Jan 2012 23:19:17 -0800
changeset 84246 e42fbf39edbf1cfe5f519c795fed79c3fdab3ab0
parent 84245 5461d5635ca9258401f96ea856217f00d30fab1d
child 84247 59cd8f499630d5fb0d67e02ae5b7e3a2468a6f7e
push id21832
push userbmo@edmorley.co.uk
push dateWed, 11 Jan 2012 17:04:15 +0000
treeherdermozilla-central@40c9f9ff9fd5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs657076
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 657076 - better error handling in FTP for e10s. r=jduell
netwerk/protocol/ftp/FTPChannelChild.cpp
netwerk/protocol/ftp/FTPChannelChild.h
netwerk/protocol/ftp/FTPChannelParent.cpp
netwerk/protocol/ftp/PFTPChannel.ipdl
--- a/netwerk/protocol/ftp/FTPChannelChild.cpp
+++ b/netwerk/protocol/ftp/FTPChannelChild.cpp
@@ -388,54 +388,52 @@ FTPChannelChild::DoOnStopRequest(const n
       mLoadGroup->RemoveRequest(this, nsnull, statusCode);
   }
 
   // This calls NeckoChild::DeallocPFTPChannel(), which deletes |this| if IPDL
   // holds the last reference.  Don't rely on |this| existing after here!
   Send__delete__(this);
 }
 
-class FTPCancelEarlyEvent : public ChannelEvent
+class FTPFailedAsyncOpenEvent : public ChannelEvent
 {
  public:
-  FTPCancelEarlyEvent(FTPChannelChild* aChild, nsresult aStatus)
+  FTPFailedAsyncOpenEvent(FTPChannelChild* aChild, nsresult aStatus)
   : mChild(aChild), mStatus(aStatus) {}
-  void Run() { mChild->DoCancelEarly(mStatus); }
+  void Run() { mChild->DoFailedAsyncOpen(mStatus); }
  private:
   FTPChannelChild* mChild;
   nsresult mStatus;
 };
 
 bool
-FTPChannelChild::RecvCancelEarly(const nsresult& statusCode)
+FTPChannelChild::RecvFailedAsyncOpen(const nsresult& statusCode)
 {
   if (mEventQ.ShouldEnqueue()) {
-    mEventQ.Enqueue(new FTPCancelEarlyEvent(this, statusCode));
+    mEventQ.Enqueue(new FTPFailedAsyncOpenEvent(this, statusCode));
   } else {
-    DoCancelEarly(statusCode);
+    DoFailedAsyncOpen(statusCode);
   }
   return true;
 }
 
 void
-FTPChannelChild::DoCancelEarly(const nsresult& statusCode)
+FTPChannelChild::DoFailedAsyncOpen(const nsresult& statusCode)
 {
-  if (mCanceled)
-    return;
+  mStatus = statusCode;
 
-  mCanceled = true;
-  mStatus = statusCode;
-  mIsPending = false;
-  
   if (mLoadGroup)
     mLoadGroup->RemoveRequest(this, nsnull, statusCode);
 
   if (mListener) {
     mListener->OnStartRequest(this, mListenerContext);
+    mIsPending = false;
     mListener->OnStopRequest(this, mListenerContext, statusCode);
+  } else {
+    mIsPending = false;
   }
 
   mListener = nsnull;
   mListenerContext = nsnull;
 
   if (mIPCOpen)
     Send__delete__(this);
 }
@@ -487,24 +485,45 @@ FTPChannelChild::Suspend()
   NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
   if (!mSuspendCount++) {
     SendSuspend();
     mEventQ.Suspend();
   }
   return NS_OK;
 }
 
+nsresult
+FTPChannelChild::AsyncCall(void (FTPChannelChild::*funcPtr)(),
+                           nsRunnableMethod<FTPChannelChild> **retval)
+{
+  nsresult rv;
+
+  nsRefPtr<nsRunnableMethod<FTPChannelChild> > event = NS_NewRunnableMethod(this, funcPtr);
+  rv = NS_DispatchToCurrentThread(event);
+  if (NS_SUCCEEDED(rv) && retval) {
+    *retval = event;
+  }
+
+  return rv;
+}
+
+void
+FTPChannelChild::CompleteResume()
+{
+  mEventQ.Resume();
+}
+
 NS_IMETHODIMP
 FTPChannelChild::Resume()
 {
   NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
 
   if (!--mSuspendCount) {
     SendResume();
-    mEventQ.Resume();    // TODO: make this async: see HttpChannelChild::Resume
+    AsyncCall(&FTPChannelChild::CompleteResume);
   }
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // FTPChannelChild::nsIChildChannel
 //-----------------------------------------------------------------------------
 
--- a/netwerk/protocol/ftp/FTPChannelChild.h
+++ b/netwerk/protocol/ftp/FTPChannelChild.h
@@ -106,38 +106,43 @@ protected:
                                       const nsCString& aContentType,
                                       const PRTime& aLastModified,
                                       const nsCString& aEntityID,
                                       const IPC::URI& aURI);
   NS_OVERRIDE bool RecvOnDataAvailable(const nsCString& data,
                                        const PRUint32& offset,
                                        const PRUint32& count);
   NS_OVERRIDE bool RecvOnStopRequest(const nsresult& statusCode);
-  NS_OVERRIDE bool RecvCancelEarly(const nsresult& statusCode);
+  NS_OVERRIDE bool RecvFailedAsyncOpen(const nsresult& statusCode);
   NS_OVERRIDE bool RecvDeleteSelf();
 
   void DoOnStartRequest(const PRInt32& aContentLength,
                         const nsCString& aContentType,
                         const PRTime& aLastModified,
                         const nsCString& aEntityID,
                         const IPC::URI& aURI);
   void DoOnDataAvailable(const nsCString& data,
                          const PRUint32& offset,
                          const PRUint32& count);
   void DoOnStopRequest(const nsresult& statusCode);
-  void DoCancelEarly(const nsresult& statusCode);
+  void DoFailedAsyncOpen(const nsresult& statusCode);
   void DoDeleteSelf();
 
   friend class FTPStartRequestEvent;
   friend class FTPDataAvailableEvent;
   friend class FTPStopRequestEvent;
-  friend class FTPCancelEarlyEvent;
+  friend class FTPFailedAsyncOpenEvent;
   friend class FTPDeleteSelfEvent;
 
 private:
+  // Called asynchronously from Resume: continues any pending calls into client.
+  void CompleteResume();
+  nsresult AsyncCall(void (FTPChannelChild::*funcPtr)(),
+                     nsRunnableMethod<FTPChannelChild> **retval = nsnull);
+
   nsCOMPtr<nsIInputStream> mUploadStream;
 
   bool mIPCOpen;
   ChannelEventQueue mEventQ;
   bool mCanceled;
   PRUint32 mSuspendCount;
   bool mIsPending;
   bool mWasOpened;
--- a/netwerk/protocol/ftp/FTPChannelParent.cpp
+++ b/netwerk/protocol/ftp/FTPChannelParent.cpp
@@ -100,40 +100,40 @@ FTPChannelParent::RecvAsyncOpen(const IP
   uri->GetSpec(uriSpec);
   LOG(("FTPChannelParent RecvAsyncOpen [this=%x uri=%s]\n",
        this, uriSpec.get()));
 #endif
 
   nsresult rv;
   nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
   if (NS_FAILED(rv))
-    return SendCancelEarly(rv);
+    return SendFailedAsyncOpen(rv);
 
   nsCOMPtr<nsIChannel> chan;
   rv = NS_NewChannel(getter_AddRefs(chan), uri, ios);
   if (NS_FAILED(rv))
-    return SendCancelEarly(rv);
+    return SendFailedAsyncOpen(rv);
 
   mChannel = static_cast<nsFtpChannel*>(chan.get());
   
   nsCOMPtr<nsIInputStream> upload(aUploadStream);
   if (upload) {
     // contentType and contentLength are ignored
     rv = mChannel->SetUploadStream(upload, EmptyCString(), 0);
     if (NS_FAILED(rv))
-      return SendCancelEarly(rv);
+      return SendFailedAsyncOpen(rv);
   }
 
   rv = mChannel->ResumeAt(aStartPos, aEntityID);
   if (NS_FAILED(rv))
-    return SendCancelEarly(rv);
+    return SendFailedAsyncOpen(rv);
 
   rv = mChannel->AsyncOpen(this, nsnull);
   if (NS_FAILED(rv))
-    return SendCancelEarly(rv);
+    return SendFailedAsyncOpen(rv);
   
   return true;
 }
 
 bool
 FTPChannelParent::RecvConnectChannel(const PRUint32& channelId)
 {
   nsresult rv;
@@ -148,31 +148,34 @@ FTPChannelParent::RecvConnectChannel(con
   LOG(("  found channel %p, rv=%08x", mChannel.get(), rv));
 
   return true;
 }
 
 bool
 FTPChannelParent::RecvCancel(const nsresult& status)
 {
-  mChannel->Cancel(status);
+  if (mChannel)
+    mChannel->Cancel(status);
   return true;
 }
 
 bool
 FTPChannelParent::RecvSuspend()
 {
-  mChannel->Suspend();
+  if (mChannel)
+    mChannel->Suspend();
   return true;
 }
 
 bool
 FTPChannelParent::RecvResume()
 {
-  mChannel->Resume();
+  if (mChannel)
+    mChannel->Resume();
   return true;
 }
 
 //-----------------------------------------------------------------------------
 // FTPChannelParent::nsIRequestObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
--- a/netwerk/protocol/ftp/PFTPChannel.ipdl
+++ b/netwerk/protocol/ftp/PFTPChannel.ipdl
@@ -64,15 +64,15 @@ parent:
   Suspend();
   Resume();
 
 child:
   OnStartRequest(PRInt32 aContentLength, nsCString aContentType,
                  PRTime aLastModified, nsCString aEntityID, URI aURI);
   OnDataAvailable(nsCString data, PRUint32 offset, PRUint32 count);
   OnStopRequest(nsresult statusCode);
-  CancelEarly(nsresult statusCode);
+  FailedAsyncOpen(nsresult statusCode);
   DeleteSelf();
 };
 
 } // namespace net
 } // namespace mozilla