Page 1 of 1

Calling cpSpaceRemoveCollisionHandler while still in contact

PostPosted: Sun Jul 15, 2012 10:08 pm
by Beernutts
HI,

I'm getting a crash when I remove a collision handler while still in contact with a object. Here's what happens.

I have this call:
cpSpaceAddCollisionHandler(pSpace, pShape1->collision_type,
pShape2->collision_type,
OnCollision, NULL, NULL, OnSeparate, NULL);

After a while, when an object collides, for certain situations, I want to remove the callback for those 2 collision types, so I call:
cpSpaceRemoveCollisionHandler(pSpace, pShape1->collision_type,
pShape2->collision_type);

Well, i get a crash when they separate, in
contactSetFilter(), at this line:
arb->handler->separate(arb, space, arb->handler->data);
as separate is now an invalid value: 0xabababab

Any suggestions? Is this an invalid situation and it shouldn't be allowed?

BTW, I'm using v5.3.4, so you'll probably suggest I upgrade, but I'd rather not at this point.

Thanks!

Re: Calling cpSpaceRemoveCollisionHandler while still in con

PostPosted: Mon Jul 16, 2012 8:52 am
by slembcke
Ah. I was going to say, I've added specific logic to handle that, but I'm not sure at which version I did it without looking through a ton of change logs.

At the moment I don't have time to get you a fully working solution, but this is how the code works in the latest code. Basically instead of calling the separate callback directly by dereferencing the dangling pointer, it calls cpArbiterCallSeparate() instead. cpArbiterCallSeparate() looks up the handler again, and then calls it. So it safely handles the case where a handler is removed while a collision is active. I don't remember offhand how much work it would take to adapt it to Chipmunk 5.x (I haven't personally worked on that in almost a year now). You might need to change some of the types

Code: Select all
static inline cpCollisionHandler *
cpSpaceLookupHandler(cpSpace *space, cpCollisionType a, cpCollisionType b)
{
   cpCollisionType types[] = {a, b};
   return (cpCollisionHandler *)cpHashSetFind(space->collisionHandlers, CP_HASH_PAIR(a, b), types);
}

static inline void
cpArbiterCallSeparate(cpArbiter *arb, cpSpace *space)
{
   // The handler needs to be looked up again as the handler cached on the arbiter may have been deleted since the last step.
   cpCollisionHandler *handler = cpSpaceLookupHandler(space, arb->a->collision_type, arb->b->collision_type);
   handler->separate(arb, space, handler->data);
}

Re: Calling cpSpaceRemoveCollisionHandler while still in con

PostPosted: Mon Jul 16, 2012 10:34 am
by Beernutts
OK, I can probably throw a fix in there for that.

I actually may just bite the bullet and upgrade, as I need to also upgrade SFML, and I might do it all in one go.

Regardless, thanks for the help!