Add a callback for top-level actors to free themselves. (bug 1285364, r=billm)
authorDavid Anderson <danderson@mozilla.com>
Wed, 13 Jul 2016 11:21:58 -0700
changeset 329986 375d352b07414af85807421054a064e31c4db868
parent 329948 80e7a1b549de94a4bdca5b23a3fd0d7f1923b878
child 329987 190fa9a5f989a43f93295d8364ac83f6e6c1e4e1
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1285364
milestone50.0a1
Add a callback for top-level actors to free themselves. (bug 1285364, r=billm)
ipc/glue/MessageChannel.cpp
ipc/ipdl/ipdl/lower.py
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -2068,20 +2068,23 @@ MessageChannel::NotifyMaybeChannelError(
     if (ChannelClosing == mChannelState) {
         // the channel closed, but we received a "Goodbye" message warning us
         // about it. no worries
         mChannelState = ChannelClosed;
         NotifyChannelClosed();
         return;
     }
 
+    Clear();
+
     // Oops, error!  Let the listener know about it.
     mChannelState = ChannelError;
+
+    // After this, the channel may be deleted.
     mListener->OnChannelError();
-    Clear();
 }
 
 void
 MessageChannel::OnNotifyMaybeChannelError()
 {
     AssertWorkerThread();
     mMonitor->AssertNotCurrentThreadOwns();
 
@@ -2223,21 +2226,22 @@ MessageChannel::Close()
 void
 MessageChannel::NotifyChannelClosed()
 {
     mMonitor->AssertNotCurrentThreadOwns();
 
     if (ChannelClosed != mChannelState)
         NS_RUNTIMEABORT("channel should have been closed!");
 
+    Clear();
+
     // OK, the IO thread just closed the channel normally.  Let the
-    // listener know about it.
+    // listener know about it. After this point the channel may be
+    // deleted.
     mListener->OnChannelClose();
-
-    Clear();
 }
 
 void
 MessageChannel::DebugAbort(const char* file, int line, const char* cond,
                            const char* why,
                            bool reply)
 {
     printf_stderr("###!!! [MessageChannel][%s][%s:%d] "
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -3238,16 +3238,17 @@ class _GenerateProtocolActorCode(ipdl.as
             makeHandlerMethod('OnCallReceived', self.interruptSwitch,
                               hasReply=1, dispatches=dispatches),
             Whitespace.NL
         ])
 
         destroysubtreevar = ExprVar('DestroySubtree')
         deallocsubtreevar = ExprVar('DeallocSubtree')
         deallocshmemvar = ExprVar('DeallocShmems')
+        deallocselfvar = ExprVar('Dealloc' + _actorName(ptype.name(), self.side))
 
         # OnProcesingError(code)
         codevar = ExprVar('aCode')
         reasonvar = ExprVar('aReason')
         onprocessingerror = MethodDefn(
             MethodDecl('OnProcessingError',
                        params=[ Param(_Result.Type(), codevar.name),
                                 Param(Type('char', const=1, ptr=1), reasonvar.name) ]))
@@ -3316,31 +3317,33 @@ class _GenerateProtocolActorCode(ipdl.as
 
         # OnChannelClose()
         onclose = MethodDefn(MethodDecl('OnChannelClose'))
         if ptype.isToplevel():
             onclose.addstmts([
                 StmtExpr(ExprCall(destroysubtreevar,
                                   args=[ _DestroyReason.NormalShutdown ])),
                 StmtExpr(ExprCall(deallocsubtreevar)),
-                StmtExpr(ExprCall(deallocshmemvar))
+                StmtExpr(ExprCall(deallocshmemvar)),
+                StmtExpr(ExprCall(deallocselfvar))
             ])
         else:
             onclose.addstmt(
                 _fatalError("`OnClose' called on non-toplevel actor"))
         self.cls.addstmts([ onclose, Whitespace.NL ])
 
         # OnChannelError()
         onerror = MethodDefn(MethodDecl('OnChannelError'))
         if ptype.isToplevel():
             onerror.addstmts([
                 StmtExpr(ExprCall(destroysubtreevar,
                                   args=[ _DestroyReason.AbnormalShutdown ])),
                 StmtExpr(ExprCall(deallocsubtreevar)),
-                StmtExpr(ExprCall(deallocshmemvar))
+                StmtExpr(ExprCall(deallocshmemvar)),
+                StmtExpr(ExprCall(deallocselfvar))
             ])
         else:
             onerror.addstmt(
                 _fatalError("`OnError' called on non-toplevel actor"))
         self.cls.addstmts([ onerror, Whitespace.NL ])
 
         # OnChannelConnected()
         onconnected = MethodDefn(MethodDecl('OnChannelConnected',
@@ -3552,16 +3555,19 @@ class _GenerateProtocolActorCode(ipdl.as
             foreachdealloc.addstmt(StmtExpr(_shmemDealloc(shmem)))
 
             deallocshmem.addstmts([
                 foreachdealloc,
                 StmtExpr(ExprCall(ExprSelect(p.shmemMapVar(), '.', 'Clear')))
             ])
             self.cls.addstmts([ deallocshmem, Whitespace.NL ])
 
+            deallocself = MethodDefn(MethodDecl(deallocselfvar.name, virtual=1))
+            self.cls.addstmts([ deallocself, Whitespace.NL ])
+
         self.implementPickling()
 
         ## private members
         self.cls.addstmt(StmtDecl(Decl(p.channelType(), 'mChannel')))
         if ptype.isToplevel():
             self.cls.addstmts([
                 StmtDecl(Decl(Type('IDMap', T=Type('ProtocolBase')),
                               p.actorMapVar().name)),