Bug 855453 - Move UnixSocket connect delay to main thread cancelable task; r=mrbkap
authorKyle Machulis <kyle@nonpolynomial.com>
Mon, 01 Apr 2013 17:26:25 -0700
changeset 138681 2050e321ca34602f3439cdc546547071e418d291
parent 138680 41823b91e31ff6aca26e7adb3fb9292469f22983
child 138682 b20eab2be2dcc2b606f50017e9703df3f9c8be08
push id350
push userbbajaj@mozilla.com
push dateMon, 29 Jul 2013 23:00:49 +0000
treeherdermozilla-release@064965b37dbd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs855453
milestone23.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 855453 - Move UnixSocket connect delay to main thread cancelable task; r=mrbkap
ipc/unixsocket/UnixSocket.cpp
--- a/ipc/unixsocket/UnixSocket.cpp
+++ b/ipc/unixsocket/UnixSocket.cpp
@@ -45,16 +45,17 @@ class UnixSocketImpl : public MessageLoo
 public:
   UnixSocketImpl(UnixSocketConsumer* aConsumer, UnixSocketConnector* aConnector,
                  const nsACString& aAddress)
     : mConsumer(aConsumer)
     , mIOLoop(nullptr)
     , mConnector(aConnector)
     , mShuttingDownOnIOThread(false)
     , mAddress(aAddress)
+    , mDelayedConnectTask(nullptr)
   {
   }
 
   ~UnixSocketImpl()
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(IsShutdownOnMainThread());
   }
@@ -106,16 +107,38 @@ public:
     mIOLoop = MessageLoopForIO::current();
     mIOLoop->WatchFileDescriptor(mFd,
                                  true,
                                  MessageLoopForIO::WATCH_READ,
                                  &mReadWatcher,
                                  this);
   }
 
+  void SetDelayedConnectTask(CancelableTask* aTask)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    mDelayedConnectTask = aTask;
+  }
+
+  void ClearDelayedConnectTask()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    mDelayedConnectTask = nullptr;
+  }
+
+  void CancelDelayedConnectTask()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    if (!mDelayedConnectTask) {
+      return;
+    }
+    mDelayedConnectTask->Cancel();
+    ClearDelayedConnectTask();
+  }
+
   /** 
    * Connect to a socket
    */
   void Connect();
 
   /** 
    * Run bind/listen to prepare for further runs of accept()
    */
@@ -130,18 +153,17 @@ public:
    * Set up flags on whatever our current file descriptor is.
    *
    * @return true if successful, false otherwise
    */
   bool SetSocketFlags();
 
   void GetSocketAddr(nsAString& aAddrStr)
   {
-    if (!mConnector)
-    {
+    if (!mConnector) {
       NS_WARNING("No connector to get socket address from!");
       aAddrStr.Truncate();
       return;
     }
     mConnector->GetSocketAddr(mAddr, aAddrStr);
   }
 
   /**
@@ -214,16 +236,21 @@ private:
    * Size of the socket address struct
    */
   socklen_t mAddrSize;
 
   /**
    * Address struct of the socket currently in use
    */
   sockaddr_any mAddr;
+
+  /**
+   * Task member for delayed connect task. Should only be access on main thread.
+   */
+  CancelableTask* mDelayedConnectTask;
 };
 
 template<class T>
 class DeleteInstanceRunnable : public nsRunnable
 {
 public:
   DeleteInstanceRunnable(T* aInstance)
   : mInstance(aInstance)
@@ -289,17 +316,17 @@ public:
   {
     MOZ_ASSERT(aImpl);
     MOZ_ASSERT(aData);
   }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
-    if(mImpl->IsShutdownOnMainThread()) {
+    if (mImpl->IsShutdownOnMainThread()) {
       NS_WARNING("mConsumer is null, aborting receive!");
       // Since we've already explicitly closed and the close happened before
       // this, this isn't really an error. Since we've warned, return OK.
       return NS_OK;
     }
 
     MOZ_ASSERT(mImpl->mConsumer);
     mImpl->mConsumer->ReceiveSocketData(mRawData);
@@ -399,16 +426,40 @@ public:
 };
 
 void SocketConnectTask::Run()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   mImpl->Connect();
 }
 
+class SocketDelayedConnectTask : public CancelableTask {
+  virtual void Run();
+
+  UnixSocketImpl* mImpl;
+public:
+  SocketDelayedConnectTask(UnixSocketImpl* aImpl) : mImpl(aImpl) { }
+
+  virtual void Cancel()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    mImpl = nullptr;
+  }
+};
+
+void SocketDelayedConnectTask::Run()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (!mImpl || mImpl->IsShutdownOnMainThread()) {
+    return;
+  }
+  mImpl->ClearDelayedConnectTask();
+  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketConnectTask(mImpl));
+}
+
 class ShutdownSocketTask : public Task {
   virtual void Run();
 
   UnixSocketImpl* mImpl;
 
 public:
   ShutdownSocketTask(UnixSocketImpl* aImpl) : mImpl(aImpl) { }
 };
@@ -441,18 +492,17 @@ UnixSocketImpl::Accept()
 
   // This will set things we don't particularly care about, but it will hand
   // back the correct structure size which is what we do care about.
   if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) {
     NS_WARNING("Cannot create socket address!");
     return;
   }
 
-  if (mFd.get() < 0)
-  {
+  if (mFd.get() < 0) {
     mFd = mConnector->Create();
     if (mFd.get() < 0) {
       return;
     }
 
     if (!SetSocketFlags()) {
       return;
     }
@@ -481,18 +531,17 @@ UnixSocketImpl::Connect()
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
   if (!mConnector) {
     NS_WARNING("No connector object available!");
     return;
   }
 
-  if(mFd.get() < 0)
-  {
+  if (mFd.get() < 0) {
     mFd = mConnector->Create();
     if (mFd.get() < 0) {
       return;
     }
   }
 
   int ret;
 
@@ -596,16 +645,18 @@ UnixSocketConsumer::SendSocketData(const
 void
 UnixSocketConsumer::CloseSocket()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mImpl) {
     return;
   }
 
+  mImpl->CancelDelayedConnectTask();
+
   // From this point on, we consider mImpl as being deleted.
   // We sever the relationship here so any future calls to listen or connect
   // will create a new implementation.
   mImpl->ShutdownOnMainThread();
 
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                    new ShutdownSocketTask(mImpl));
 
@@ -794,17 +845,19 @@ UnixSocketConsumer::ConnectSocket(UnixSo
     return false;
   }
 
   nsCString addr(aAddress);
   mImpl = new UnixSocketImpl(this, connector.forget(), addr);
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
   mConnectionStatus = SOCKET_CONNECTING;
   if (aDelayMs > 0) {
-    ioLoop->PostDelayedTask(FROM_HERE, new SocketConnectTask(mImpl), aDelayMs);
+    SocketDelayedConnectTask* connectTask = new SocketDelayedConnectTask(mImpl);
+    mImpl->SetDelayedConnectTask(connectTask);
+    MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
   } else {
     ioLoop->PostTask(FROM_HERE, new SocketConnectTask(mImpl));
   }
   return true;
 }
 
 bool
 UnixSocketConsumer::ListenSocket(UnixSocketConnector* aConnector)