| Summary: | SDL_android.c s_active not being atomic | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Isaias Brunet <mscsirmaster> |
| Component: | *don't know* | Assignee: | Ryan C. Gordon <icculus> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | critical | ||
| Priority: | P2 | ||
| Version: | 2.0.9 | ||
| Hardware: | All | ||
| OS: | Android (All) | ||
Fixed, thanks! https://hg.libsdl.org/SDL/rev/3ef8a628853d |
This bug cause a false assert due to multiple threads modifying the same variable without any atomic operation. Bug lines: SDL_android.c static int s_active = 0; ... static SDL_bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env) { const int capacity = 16; if ((*env)->PushLocalFrame(env, capacity) < 0) { SDL_SetError("Failed to allocate enough JVM local references"); return SDL_FALSE; } ++s_active; refholder->m_env = env; return SDL_TRUE; } ... static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder) { #ifdef DEBUG_JNI SDL_Log("Leaving function %s", refholder->m_func); #endif if (refholder->m_env) { JNIEnv* env = refholder->m_env; (*env)->PopLocalFrame(env, NULL); --s_active; } } ... static SDL_bool LocalReferenceHolder_IsActive(void) { return s_active > 0; } Solution: static SDL_atomic_t s_active = { 0 }; ... static SDL_bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env) { const int capacity = 16; if ((*env)->PushLocalFrame(env, capacity) < 0) { SDL_SetError("Failed to allocate enough JVM local references"); return SDL_FALSE; } SDL_AtomicIncRef(&s_active); refholder->m_env = env; return SDL_TRUE; } ... static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder) { #ifdef DEBUG_JNI SDL_Log("Leaving function %s", refholder->m_func); #endif if (refholder->m_env) { JNIEnv* env = refholder->m_env; (*env)->PopLocalFrame(env, NULL); SDL_AtomicDecRef(&s_active); } } ... static SDL_bool LocalReferenceHolder_IsActive(void) { return SDL_AtomicGet(&s_active) > 0; } Extra bug lines: In some branches and [default] there is a line modified to use directly s_active, and should instead use LocalReferenceHolder_IsActive. SDL_assert((s_active > 0)); Solution: SDL_assert(LocalReferenceHolder_IsActive());