Bug 1541114 - Check mIPCOpen before sending messages r=mayhemer
authorKershaw Chang <kershaw@mozilla.com>
Fri, 12 Apr 2019 05:04:22 +0000
changeset 469213 1cf54b6a1c902ef00b7b3b68c08a4b8aa61b8703
parent 469212 d1b15e1a37f0f7098c0800ac89239540712210a6
child 469214 a632dfa60af6edd4f7dd03d404d898b6222b56c3
push id35858
push usershindli@mozilla.com
push dateFri, 12 Apr 2019 09:34:00 +0000
treeherdermozilla-central@a632dfa60af6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1541114
milestone68.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 1541114 - Check mIPCOpen before sending messages r=mayhemer To avoid sending ipc messages after the ipc channel is closed, check |mIPCOpen| before sending messages. Differential Revision: https://phabricator.services.mozilla.com/D26089
dom/network/TCPServerSocketParent.cpp
dom/network/TCPSocket.cpp
dom/network/TCPSocketParent.cpp
dom/network/TCPSocketParent.h
--- a/dom/network/TCPServerSocketParent.cpp
+++ b/dom/network/TCPServerSocketParent.cpp
@@ -47,18 +47,16 @@ TCPServerSocketParent::TCPServerSocketPa
 
 TCPServerSocketParent::~TCPServerSocketParent() {}
 
 void TCPServerSocketParent::Init() {
   NS_ENSURE_SUCCESS_VOID(mServerSocket->Init());
 }
 
 nsresult TCPServerSocketParent::SendCallbackAccept(TCPSocketParent* socket) {
-  socket->AddIPDLReference();
-
   nsresult rv;
 
   nsString host;
   rv = socket->GetHost(host);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to get host from nsITCPSocketParent");
     return NS_ERROR_FAILURE;
   }
@@ -67,16 +65,20 @@ nsresult TCPServerSocketParent::SendCall
   rv = socket->GetPort(&port);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to get port from nsITCPSocketParent");
     return NS_ERROR_FAILURE;
   }
 
   if (mNeckoParent) {
     if (mNeckoParent->SendPTCPSocketConstructor(socket, host, port)) {
+      // Call |AddIPDLReference| after the consructor message is sent
+      // successfully, otherwise |socket| could be leaked.
+      socket->AddIPDLReference();
+
       mozilla::Unused << PTCPServerSocketParent::SendCallbackAccept(socket);
     } else {
       NS_ERROR("Sending data from PTCPSocketParent was failed.");
     }
   } else {
     NS_ERROR("The member value for NeckoParent is wrong.");
   }
   return NS_OK;
--- a/dom/network/TCPSocket.cpp
+++ b/dom/network/TCPSocket.cpp
@@ -381,17 +381,17 @@ void TCPSocket::NotifyCopyComplete(nsres
     nsCOMPtr<nsIInputStream> stream = mPendingData[i];
     uint64_t available = 0;
     if (NS_SUCCEEDED(stream->Available(&available))) {
       bufferedAmount += available;
     }
   }
   mBufferedAmount = bufferedAmount;
 
-  if (mSocketBridgeParent) {
+  if (mSocketBridgeParent && mSocketBridgeParent->IPCOpen()) {
     mozilla::Unused << mSocketBridgeParent->SendUpdateBufferedAmount(
         BufferedAmount(), mTrackingNumber);
   }
 
   if (NS_FAILED(aStatus)) {
     MaybeReportErrorAndCloseIfOpen(aStatus);
     return;
   }
@@ -441,17 +441,17 @@ void TCPSocket::ActivateTLS() {
   nsCOMPtr<nsISSLSocketControl> socketControl = do_QueryInterface(securityInfo);
   if (socketControl) {
     socketControl->StartTLS();
   }
 }
 
 NS_IMETHODIMP
 TCPSocket::FireErrorEvent(const nsAString& aName, const nsAString& aType) {
-  if (mSocketBridgeParent) {
+  if (mSocketBridgeParent && mSocketBridgeParent->IPCOpen()) {
     mSocketBridgeParent->FireErrorEvent(aName, aType, mReadyState);
     return NS_OK;
   }
 
   TCPSocketErrorEventInit init;
   init.mBubbles = false;
   init.mCancelable = false;
   init.mName = aName;
@@ -462,17 +462,17 @@ TCPSocket::FireErrorEvent(const nsAStrin
   MOZ_ASSERT(event);
   event->SetTrusted(true);
   DispatchEvent(*event);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TCPSocket::FireEvent(const nsAString& aType) {
-  if (mSocketBridgeParent) {
+  if (mSocketBridgeParent && mSocketBridgeParent->IPCOpen()) {
     mSocketBridgeParent->FireEvent(aType, mReadyState);
     return NS_OK;
   }
 
   AutoJSAPI api;
   if (NS_WARN_IF(!api.Init(GetOwnerGlobal()))) {
     return NS_ERROR_FAILURE;
   }
@@ -939,17 +939,17 @@ TCPSocket::OnDataAvailable(nsIRequest* a
     buffer.SetCapacity(aCount);
     uint32_t actual;
     nsresult rv = aStream->Read(reinterpret_cast<char*>(buffer.Elements()),
                                 aCount, &actual);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(actual == aCount);
     buffer.SetLength(actual);
 
-    if (mSocketBridgeParent) {
+    if (mSocketBridgeParent && mSocketBridgeParent->IPCOpen()) {
       mSocketBridgeParent->FireArrayBufferDataEvent(buffer, mReadyState);
       return NS_OK;
     }
 
     AutoJSAPI api;
     if (!api.Init(GetOwnerGlobal())) {
       return NS_ERROR_FAILURE;
     }
@@ -962,17 +962,17 @@ TCPSocket::OnDataAvailable(nsIRequest* a
     FireDataEvent(cx, NS_LITERAL_STRING("data"), value);
     return NS_OK;
   }
 
   nsCString data;
   nsresult rv = mInputStreamScriptable->ReadBytes(aCount, data);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (mSocketBridgeParent) {
+  if (mSocketBridgeParent && mSocketBridgeParent->IPCOpen()) {
     mSocketBridgeParent->FireStringDataEvent(data, mReadyState);
     return NS_OK;
   }
 
   AutoJSAPI api;
   if (!api.Init(GetOwnerGlobal())) {
     return NS_ERROR_FAILURE;
   }
@@ -1001,16 +1001,18 @@ TCPSocket::OnStopRequest(nsIRequest* aRe
   }
 
   // We call this even if there is no error.
   MaybeReportErrorAndCloseIfOpen(aStatus);
   return NS_OK;
 }
 
 void TCPSocket::SetSocketBridgeParent(TCPSocketParent* aBridgeParent) {
+  MOZ_ASSERT(NS_IsMainThread());
+
   mSocketBridgeParent = aBridgeParent;
 }
 
 NS_IMETHODIMP
 TCPSocket::UpdateReadyState(uint32_t aReadyState) {
   MOZ_ASSERT(mSocketBridgeChild);
   mReadyState = static_cast<TCPReadyState>(aReadyState);
   return NS_OK;
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -325,16 +325,17 @@ nsresult TCPSocketParent::GetPort(uint16
     return NS_ERROR_FAILURE;
   }
   *aPort = mSocket->Port();
   return NS_OK;
 }
 
 void TCPSocketParent::ActorDestroy(ActorDestroyReason why) {
   if (mSocket) {
+    mSocket->SetSocketBridgeParent(nullptr);
     mSocket->Close();
   }
   mSocket = nullptr;
 }
 
 mozilla::ipc::IPCResult TCPSocketParent::RecvRequestDelete() {
   mozilla::Unused << Send__delete__(this);
   return IPC_OK();
--- a/dom/network/TCPSocketParent.h
+++ b/dom/network/TCPSocketParent.h
@@ -29,16 +29,18 @@ class TCPSocket;
 class TCPSocketParentBase : public nsISupports {
  public:
   NS_DECL_CYCLE_COLLECTION_CLASS(TCPSocketParentBase)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   void AddIPDLReference();
   void ReleaseIPDLReference();
 
+  bool IPCOpen() const { return mIPCOpen; }
+
  protected:
   TCPSocketParentBase();
   virtual ~TCPSocketParentBase();
 
   RefPtr<TCPSocket> mSocket;
   bool mIPCOpen;
 };