Bug 640901: Clean up managees when manager ctor fails. r=cjones
authorBen Turner <bent.mozilla@gmail.com>
Mon, 21 Mar 2011 11:00:00 -0500
changeset 63894 6f5809f445328167f2eb839a9525d4b41ef14e46
parent 63893 e9ab3e8d43031700ae02ca5104bff6d91cc75453
child 63895 4d230c10d507e776f4e2f62bc5ff64842ea0c992
push id19278
push usercjones@mozilla.com
push dateFri, 25 Mar 2011 17:56:48 +0000
treeherdermozilla-central@4d230c10d507 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs640901
milestone2.2a1pre
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 640901: Clean up managees when manager ctor fails. r=cjones
gfx/layers/ipc/ShadowLayerParent.cpp
ipc/glue/ProtocolUtils.h
ipc/ipdl/ipdl/lower.py
--- a/gfx/layers/ipc/ShadowLayerParent.cpp
+++ b/gfx/layers/ipc/ShadowLayerParent.cpp
@@ -94,15 +94,19 @@ ShadowLayerParent::ActorDestroy(ActorDes
     }
     break;
 
   case AbnormalShutdown:
   case NormalShutdown:
     // let IPDL-generated code automatically clean up Shmems and so
     // forth; our channel is disconnected anyway
     break;
+
+  case FailedConstructor:
+    NS_RUNTIMEABORT("FailedConstructor isn't possible in PLayers");
+    return;                     // unreached
   }
 
   mLayer = NULL;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -90,16 +90,17 @@ struct Trigger
     int32 mMsg;
 };
 
 template<class ListenerT>
 class /*NS_INTERFACE_CLASS*/ IProtocolManager
 {
 public:
     enum ActorDestroyReason {
+        FailedConstructor,
         Deletion,
         AncestorDeletion,
         NormalShutdown,
         AbnormalShutdown
     };
 
     typedef base::ProcessHandle ProcessHandle;
 
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -112,18 +112,20 @@ def _actorName(pname, side):
     """|pname| is the protocol name. |side| is 'Parent' or 'Child'."""
     tag = side
     if not tag[0].isupper():  tag = side.title()
     return pname + tag
 
 def _actorIdType():
     return Type('int32')
 
-def _actorId(actor):
-    return ExprSelect(actor, '->', 'mId')
+def _actorId(actor=None):
+    if actor is not None:
+        return ExprSelect(actor, '->', 'mId')
+    return ExprVar('mId')
 
 def _actorHId(actorhandle):
     return ExprSelect(actorhandle, '.', 'mId')
 
 def _actorChannel(actor):
     return ExprSelect(actor, '->', 'mChannel')
 
 def _actorManager(actor):
@@ -436,16 +438,17 @@ def _destroyMethod():
 class _DestroyReason:
     @staticmethod
     def Type():  return Type('ActorDestroyReason')
 
     Deletion = ExprVar('Deletion')
     AncestorDeletion = ExprVar('AncestorDeletion')
     NormalShutdown = ExprVar('NormalShutdown')
     AbnormalShutdown = ExprVar('AbnormalShutdown')
+    FailedConstructor = ExprVar('FailedConstructor')
 
 ##-----------------------------------------------------------------------------
 ## Intermediate representation (IR) nodes used during lowering
 
 class _ConvertToCxxType(TypeVisitor):
     def __init__(self, side):  self.side = side
 
     def visitBuiltinCxxType(self, t):
@@ -2955,23 +2958,34 @@ class _GenerateProtocolActorCode(ipdl.as
         kidsvar = ExprVar('kids')
         ivar = ExprVar('i')
         ithkid = ExprIndex(kidsvar, ivar)
 
         destroysubtree = MethodDefn(MethodDecl(
             destroysubtreevar.name,
             params=[ Decl(_DestroyReason.Type(), whyvar.name) ]))
 
+        if ptype.isManaged():
+            destroysubtree.addstmt(
+                Whitespace('// Unregister from our manager.\n', indent=1))
+            destroysubtree.addstmts(self.unregisterActor())
+            destroysubtree.addstmt(Whitespace.NL)
+
         if ptype.isManager():
             # only declare this for managers to avoid unused var warnings
             destroysubtree.addstmts([
                 StmtDecl(
                     Decl(_DestroyReason.Type(), subtreewhyvar.name),
                     init=ExprConditional(
-                        ExprBinary(_DestroyReason.Deletion, '==', whyvar),
+                        ExprBinary(
+                            ExprBinary(whyvar, '==',
+                                       _DestroyReason.Deletion),
+                            '||',
+                            ExprBinary(whyvar, '==',
+                                       _DestroyReason.FailedConstructor)),
                         _DestroyReason.AncestorDeletion, whyvar)),
                 Whitespace.NL
             ])
 
         for managed in ptype.manages:
             foreachdestroy = StmtFor(
                 init=Param(Type.UINT32, ivar.name, ExprLiteral.ZERO),
                 cond=ExprBinary(ivar, '<', _callCxxArrayLength(kidsvar)),
@@ -2986,20 +3000,25 @@ class _GenerateProtocolActorCode(ipdl.as
                     '// Recursively shutting down %s kids\n'% (managed.name()),
                     indent=1),
                 StmtDecl(
                     Decl(p.managedVarType(managed, self.side), kidsvar.name),
                     init=p.managedVar(managed, self.side)),
                 foreachdestroy,
             ])
             destroysubtree.addstmt(block)
-        # finally, destroy "us"
-        destroysubtree.addstmt(StmtExpr(
-            ExprCall(_destroyMethod(), args=[ whyvar ])))
-        
+
+        if len(ptype.manages):
+            destroysubtree.addstmt(Whitespace.NL)
+        destroysubtree.addstmts([ Whitespace('// Finally, destroy "us".\n',
+                                             indent=1),
+                                  StmtExpr(ExprCall(_destroyMethod(),
+                                                    args=[ whyvar ]))
+                                ])
+
         self.cls.addstmts([ destroysubtree, Whitespace.NL ])
 
         ## DeallocSubtree()
         deallocsubtree = MethodDefn(MethodDecl(deallocsubtreevar.name))
         for managed in ptype.manages:
             foreachrecurse = StmtFor(
                 init=Param(Type.UINT32, ivar.name, ExprLiteral.ZERO),
                 cond=ExprBinary(ivar, '<', _callCxxArrayLength(kidsvar)),
@@ -4156,24 +4175,21 @@ class _GenerateProtocolActorCode(ipdl.as
                                          self.side),
                 actorvar)),
             StmtExpr(ExprAssn(_actorState(actorvar),
                               _startState(actorproto, fq=1)))
         ]
 
     def failCtorIf(self, md, cond):
         actorvar = md.actorDecl().var()
+        type = md.decl.type.constructedType()
         failif = StmtIf(cond)
-        failif.addifstmts(
-            self.unregisterActor(actorvar)
-            + [ StmtExpr(self.callRemoveActor(
-                    actorvar,
-                    ipdltype=md.decl.type.constructedType())),
-                StmtReturn(ExprLiteral.NULL),
-            ])
+        failif.addifstmts(self.destroyActor(md, actorvar,
+                                            why=_DestroyReason.FailedConstructor)
+                          + [ StmtReturn(ExprLiteral.NULL) ])
         return [ failif ]
 
     def genHelperCtor(self, md):
         helperdecl = self.makeSendMethodDecl(md)
         helperdecl.params = helperdecl.params[1:]
         helper = MethodDefn(helperdecl)
 
         callctor = self.callAllocActor(md, retsems='out')
@@ -4234,27 +4250,34 @@ class _GenerateProtocolActorCode(ipdl.as
 
         method.addstmts(
             [ ifsendok ]
             + self.dtorEpilogue(md, actor.var())
             + [ Whitespace.NL, StmtReturn(sendok) ])
 
         return method
 
+    def destroyActor(self, md, actorexpr, why=_DestroyReason.Deletion):
+        if md.decl.type.isCtor():
+            destroyedType = md.decl.type.constructedType()
+        else:
+            destroyedType = self.protocol.decl.type
+        return ([ StmtExpr(self.callActorDestroy(actorexpr, why)),
+                  StmtExpr(self.callDeallocSubtree(md, actorexpr)),
+                  StmtExpr(self.callRemoveActor(
+                      actorexpr,
+                      manager=self.protocol.managerVar(actorexpr),
+                      ipdltype=destroyedType))
+                ])
+
     def dtorPrologue(self, actorexpr):
         return [ self.failIfNullActor(actorexpr), Whitespace.NL ]
 
     def dtorEpilogue(self, md, actorexpr):
-        return (self.unregisterActor(actorexpr)
-                + [ StmtExpr(self.callActorDestroy(actorexpr)),
-                    StmtExpr(self.callDeallocSubtree(md, actorexpr)),
-                    StmtExpr(self.callRemoveActor(
-                        actorexpr,
-                        manager=self.protocol.managerVar(actorexpr)))
-                  ])
+        return self.destroyActor(md, actorexpr)
 
     def genAsyncSendMethod(self, md):
         method = MethodDefn(self.makeSendMethodDecl(md))
         msgvar, stmts = self.makeMessage(md, errfnSend)
         sendok, sendstmts = self.sendAsync(md, msgvar)
         method.addstmts(stmts
                         +[ Whitespace.NL ]
                         + sendstmts
@@ -4365,17 +4388,17 @@ class _GenerateProtocolActorCode(ipdl.as
 
     # helper methods
 
     def failIfNullActor(self, actorExpr, retOnNull=ExprLiteral.FALSE):
         failif = StmtIf(ExprNot(actorExpr))
         failif.addifstmt(StmtReturn(retOnNull))
         return failif
 
-    def unregisterActor(self, actorexpr):
+    def unregisterActor(self, actorexpr=None):
         return [ StmtExpr(ExprCall(self.protocol.unregisterMethod(actorexpr),
                                    args=[ _actorId(actorexpr) ])),
                  StmtExpr(ExprAssn(_actorId(actorexpr), _FREED_ACTOR_ID)) ]
 
     def makeMessage(self, md, errfn, fromActor=None):
         msgvar = self.msgvar
         routingId = self.protocol.routingId(fromActor)
         this = None