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 idunknown
push userunknown
push dateunknown
reviewerscjones
bugs640901
milestone2.2a1pre
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