From dc90c45a485e7b3d8a29987d99239d7abf6673de Mon Sep 17 00:00:00 2001 From: slembcke Date: Wed, 12 Dec 2012 13:14:41 -0600 Subject: [PATCH] Fix for a rare but fatal sleeping/contact graph bug. --- include/chipmunk/chipmunk_private.h | 6 ++++++ src/cpArbiter.c | 2 +- src/cpSpace.c | 9 +++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/chipmunk/chipmunk_private.h b/include/chipmunk/chipmunk_private.h index 33532922..1528dc04 100644 --- a/include/chipmunk/chipmunk_private.h +++ b/include/chipmunk/chipmunk_private.h @@ -257,6 +257,12 @@ cpArbiterThreadForBody(cpArbiter *arb, cpBody *body) return (arb->body_a == body ? &arb->thread_a : &arb->thread_b); } +static inline cpBool +cpArbiterIsFiltered(cpArbiter *arb) +{ + return (arb->contacts == NULL); +} + void cpArbiterUnthread(cpArbiter *arb); void cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, struct cpCollisionHandler *handler, cpShape *a, cpShape *b); diff --git a/src/cpArbiter.c b/src/cpArbiter.c index 690d2fd1..c231c254 100644 --- a/src/cpArbiter.c +++ b/src/cpArbiter.c @@ -221,7 +221,7 @@ void cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, cpCollisionHandler *handler, cpShape *a, cpShape *b) { // Arbiters without contact data may exist if a collision function rejected the collision. - if(arb->contacts){ + if(!cpArbiterIsFiltered(arb)){ // Iterate over the possible pairs to look for hash value matches. for(int i=0; inumContacts; i++){ cpContact *old = &arb->contacts[i]; diff --git a/src/cpSpace.c b/src/cpSpace.c index 6501bca0..eb4c37bf 100644 --- a/src/cpSpace.c +++ b/src/cpSpace.c @@ -340,8 +340,13 @@ cachedArbitersFilter(cpArbiter *arb, struct arbiterFilterContext *context) // Call separate when removing shapes. if(shape && arb->state != cpArbiterStateCached) cpArbiterCallSeparate(arb, context->space); - cpArbiterUnthread(arb); - cpArrayDeleteObj(context->space->arbiters, arb); + // If the arbiter is active (non-sensor/filtered) it will have a contacts array. + // TODO is this too much of a hack?... + if(!cpArbiterIsFiltered(arb)){ + cpArbiterUnthread(arb); + cpArrayDeleteObj(context->space->arbiters, arb); + } + cpArrayPush(context->space->pooledArbiters, arb); return cpFalse;