mirror of https://github.com/axmolengine/axmol.git
Merge pull request #6162 from dumganhar/pull/6160
Fixed a potential crash in EventDispatcher, based on PR #6160
This commit is contained in:
commit
c2b8557efb
|
@ -340,6 +340,27 @@ void EventDispatcher::removeEventListenersForTarget(Node* target, bool recursive
|
|||
}
|
||||
}
|
||||
|
||||
// Bug fix: ensure there are no references to the node in the list of listeners to be added.
|
||||
// If we find any listeners associated with the destroyed node in this list then remove them.
|
||||
// This is to catch the scenario where the node gets destroyed before it's listener
|
||||
// is added into the event dispatcher fully. This could happen if a node registers a listener
|
||||
// and gets destroyed while we are dispatching an event (touch etc.)
|
||||
for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); )
|
||||
{
|
||||
EventListener * listener = *iter;
|
||||
|
||||
if (listener->getSceneGraphPriority() == target)
|
||||
{
|
||||
listener->setRegistered(false);
|
||||
listener->release();
|
||||
iter = _toAddedListeners.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
const auto& children = target->getChildren();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "NewEventDispatcherTest.h"
|
||||
#include "testResource.h"
|
||||
#include "CCAutoreleasePool.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -27,7 +28,8 @@ std::function<Layer*()> createFunctions[] =
|
|||
CL(PauseResumeTargetTest),
|
||||
CL(Issue4129),
|
||||
CL(Issue4160),
|
||||
CL(DanglingNodePointersTest)
|
||||
CL(DanglingNodePointersTest),
|
||||
CL(RegisterAndUnregisterWhileEventHanldingTest)
|
||||
};
|
||||
|
||||
unsigned int TEST_CASE_COUNT = sizeof(createFunctions) / sizeof(createFunctions[0]);
|
||||
|
@ -1413,3 +1415,44 @@ std::string DanglingNodePointersTest::subtitle() const
|
|||
"CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS == 1\n&& COCOS2D_DEBUG > 0";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
RegisterAndUnregisterWhileEventHanldingTest::RegisterAndUnregisterWhileEventHanldingTest()
|
||||
{
|
||||
Point origin = Director::getInstance()->getVisibleOrigin();
|
||||
Size size = Director::getInstance()->getVisibleSize();
|
||||
|
||||
auto callback1 = [=](DanglingNodePointersTestSprite * sprite)
|
||||
{
|
||||
auto callback2 = [](DanglingNodePointersTestSprite * sprite)
|
||||
{
|
||||
CCASSERT(false, "This should never get called!");
|
||||
};
|
||||
|
||||
{
|
||||
AutoreleasePool pool;
|
||||
|
||||
auto sprite2 = DanglingNodePointersTestSprite::create(callback2);
|
||||
sprite2->setTexture("Images/CyanSquare.png");
|
||||
sprite2->setPosition(origin+Point(size.width/2, size.height/2));
|
||||
|
||||
addChild(sprite2, 0);
|
||||
removeChild(sprite2);
|
||||
}
|
||||
};
|
||||
|
||||
auto sprite1 = DanglingNodePointersTestSprite::create(callback1);
|
||||
sprite1->setTexture("Images/CyanSquare.png");
|
||||
sprite1->setPosition(origin+Point(size.width/2, size.height/2));
|
||||
addChild(sprite1, -10);
|
||||
}
|
||||
|
||||
std::string RegisterAndUnregisterWhileEventHanldingTest::title() const
|
||||
{
|
||||
return "RegisterAndUnregisterWhileEventHanldingTest";
|
||||
}
|
||||
|
||||
std::string RegisterAndUnregisterWhileEventHanldingTest::subtitle() const
|
||||
{
|
||||
return "Tap the square multiple times - should not crash!";
|
||||
}
|
||||
|
|
|
@ -217,4 +217,14 @@ public:
|
|||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
class RegisterAndUnregisterWhileEventHanldingTest : public EventDispatcherTestDemo
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(RegisterAndUnregisterWhileEventHanldingTest);
|
||||
RegisterAndUnregisterWhileEventHanldingTest();
|
||||
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
#endif /* defined(__samples__NewEventDispatcherTest__) */
|
||||
|
|
Loading…
Reference in New Issue