Browse Source

char: fix crash during Character destructor (regression)

This was a regression in 0bb81a43c9e4fffb37cc2234c1b0fbae42020ceb which was not keeping an edge case in mind if a weak pointer is locked during object destruction.  This issue was fixed by 525a05ea2b1d00a1db901f883f1755943aeff33c, but that is not enough since it causes CharacterJointEffect::get_character() to return null now, so we need a separate method to check if a CharacterJointEffect belongs to a given character.  This is more efficient, too.

Fixes #330
rdb 7 years ago
parent
commit
3d49986ce2

+ 6 - 6
panda/src/char/characterJoint.cxx

@@ -214,7 +214,7 @@ bool CharacterJoint::
 remove_net_transform(PandaNode *node) {
 remove_net_transform(PandaNode *node) {
   CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
   CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
   if (effect != (RenderEffect *)NULL &&
   if (effect != (RenderEffect *)NULL &&
-      DCAST(CharacterJointEffect, effect)->get_character() == _character) {
+      DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
     node->clear_effect(CharacterJointEffect::get_class_type());
     node->clear_effect(CharacterJointEffect::get_class_type());
   }
   }
 
 
@@ -244,7 +244,7 @@ clear_net_transforms() {
 
 
     CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
     CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
     if (effect != (RenderEffect *)NULL &&
     if (effect != (RenderEffect *)NULL &&
-        DCAST(CharacterJointEffect, effect)->get_character() == _character) {
+        DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
       node->clear_effect(CharacterJointEffect::get_class_type());
       node->clear_effect(CharacterJointEffect::get_class_type());
     }
     }
   }
   }
@@ -306,7 +306,7 @@ bool CharacterJoint::
 remove_local_transform(PandaNode *node) {
 remove_local_transform(PandaNode *node) {
   CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
   CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
   if (effect != (RenderEffect *)NULL &&
   if (effect != (RenderEffect *)NULL &&
-      DCAST(CharacterJointEffect, effect)->get_character() == _character) {
+      DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
     node->clear_effect(CharacterJointEffect::get_class_type());
     node->clear_effect(CharacterJointEffect::get_class_type());
   }
   }
 
 
@@ -336,7 +336,7 @@ clear_local_transforms() {
 
 
     CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
     CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
     if (effect != (RenderEffect *)NULL &&
     if (effect != (RenderEffect *)NULL &&
-        DCAST(CharacterJointEffect, effect)->get_character() == _character) {
+        DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
       node->clear_effect(CharacterJointEffect::get_class_type());
       node->clear_effect(CharacterJointEffect::get_class_type());
     }
     }
   }
   }
@@ -427,7 +427,7 @@ set_character(Character *character) {
 
 
         CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
         CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
         if (effect != (RenderEffect *)NULL &&
         if (effect != (RenderEffect *)NULL &&
-            DCAST(CharacterJointEffect, effect)->get_character() == _character) {
+            DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
           node->clear_effect(CharacterJointEffect::get_class_type());
           node->clear_effect(CharacterJointEffect::get_class_type());
         }
         }
       }
       }
@@ -438,7 +438,7 @@ set_character(Character *character) {
 
 
         CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
         CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
         if (effect != (RenderEffect *)NULL &&
         if (effect != (RenderEffect *)NULL &&
-            DCAST(CharacterJointEffect, effect)->get_character() == _character) {
+            DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
           node->clear_effect(CharacterJointEffect::get_class_type());
           node->clear_effect(CharacterJointEffect::get_class_type());
         }
         }
       }
       }

+ 10 - 0
panda/src/char/characterJointEffect.I

@@ -27,3 +27,13 @@ INLINE PT(Character) CharacterJointEffect::
 get_character() const {
 get_character() const {
   return _character.lock();
   return _character.lock();
 }
 }
+
+/**
+ * Returns true if this CharacterJointEffect contains the given Character.
+ * This exists because it is faster to check than get_character() and can even
+ * be called while the Character is destructing.
+ */
+INLINE bool CharacterJointEffect::
+matches_character(Character *character) const {
+  return _character == character;
+}

+ 2 - 0
panda/src/char/characterJointEffect.h

@@ -41,6 +41,8 @@ PUBLISHED:
   INLINE PT(Character) get_character() const;
   INLINE PT(Character) get_character() const;
 
 
 public:
 public:
+  INLINE bool matches_character(Character *character) const;
+
   virtual bool safe_to_transform() const;
   virtual bool safe_to_transform() const;
   virtual bool safe_to_combine() const;
   virtual bool safe_to_combine() const;
   virtual void output(ostream &out) const;
   virtual void output(ostream &out) const;