Calling cpSpaceRemoveCollisionHandler while still in contact

Discuss any Chipmunk bugs here.
Post Reply
Beernutts
Posts: 10
Joined: Fri May 06, 2011 9:12 pm
Contact:

Calling cpSpaceRemoveCollisionHandler while still in contact

Post 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!
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Calling cpSpaceRemoveCollisionHandler while still in con

Post 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);
}
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Beernutts
Posts: 10
Joined: Fri May 06, 2011 9:12 pm
Contact:

Re: Calling cpSpaceRemoveCollisionHandler while still in con

Post 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!
Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests