From c674ee1a0a9c636800c400a175cc25884c591478 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Mar 2006 01:18:29 +0000 Subject: [PATCH] Fixed bug #150 memory leak in SDL_thread.c --- src/thread/SDL_thread.c | 65 ++++++++++++++++-------------------- src/thread/irix/SDL_syssem.c | 19 +---------- 2 files changed, 30 insertions(+), 54 deletions(-) diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c index ffb69713a..4a8a007a3 100644 --- a/src/thread/SDL_thread.c +++ b/src/thread/SDL_thread.c @@ -37,20 +37,13 @@ static int SDL_maxthreads = 0; static int SDL_numthreads = 0; static SDL_Thread **SDL_Threads = NULL; static SDL_mutex *thread_lock = NULL; -int _creating_thread_lock = 0; int SDL_ThreadsInit(void) { int retval; retval = 0; - /* Set the thread lock creation flag so that we can reuse an - existing lock on the system - since this mutex never gets - destroyed (see SDL_ThreadsQuit()), we want to reuse it. - */ - _creating_thread_lock = 1; thread_lock = SDL_CreateMutex(); - _creating_thread_lock = 0; if ( thread_lock == NULL ) { retval = -1; } @@ -76,15 +69,13 @@ void SDL_ThreadsQuit() /* Routines for manipulating the thread list */ static void SDL_AddThread(SDL_Thread *thread) { - SDL_Thread **threads; - /* WARNING: If the very first threads are created simultaneously, then there could be a race condition causing memory corruption. In practice, this isn't a problem because by definition there is only one thread running the first time this is called. */ - if ( thread_lock == NULL ) { + if ( !thread_lock ) { if ( SDL_ThreadsInit() < 0 ) { return; } @@ -97,17 +88,14 @@ static void SDL_AddThread(SDL_Thread *thread) SDL_numthreads, SDL_maxthreads); #endif if ( SDL_numthreads == SDL_maxthreads ) { - threads=(SDL_Thread **)SDL_malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)* - (sizeof *threads)); + SDL_Thread **threads; + threads = (SDL_Thread **)SDL_realloc(SDL_Threads, + (SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads)); if ( threads == NULL ) { SDL_OutOfMemory(); goto done; } - SDL_memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads)); SDL_maxthreads += ARRAY_CHUNKSIZE; - if ( SDL_Threads ) { - SDL_free(SDL_Threads); - } SDL_Threads = threads; } SDL_Threads[SDL_numthreads++] = thread; @@ -119,30 +107,35 @@ static void SDL_DelThread(SDL_Thread *thread) { int i; - if ( thread_lock ) { - SDL_mutexP(thread_lock); - for ( i=0; i 0 ) { - while ( i < SDL_numthreads ) { - SDL_Threads[i] = SDL_Threads[i+1]; - ++i; - } - } else { - SDL_maxthreads = 0; - SDL_free(SDL_Threads); - SDL_Threads = NULL; + } + if ( i < SDL_numthreads ) { + if ( --SDL_numthreads > 0 ) { + while ( i < SDL_numthreads ) { + SDL_Threads[i] = SDL_Threads[i+1]; + ++i; } + } else { + SDL_maxthreads = 0; + SDL_free(SDL_Threads); + SDL_Threads = NULL; + } #ifdef DEBUG_THREADS - printf("Deleting thread (%d left - %d max)\n", - SDL_numthreads, SDL_maxthreads); + printf("Deleting thread (%d left - %d max)\n", + SDL_numthreads, SDL_maxthreads); #endif - } - SDL_mutexV(thread_lock); + } + SDL_mutexV(thread_lock); + + if ( SDL_Threads == NULL ) { + SDL_ThreadsQuit(); } } diff --git a/src/thread/irix/SDL_syssem.c b/src/thread/irix/SDL_syssem.c index 5aefd3f1e..8b3311b58 100644 --- a/src/thread/irix/SDL_syssem.c +++ b/src/thread/irix/SDL_syssem.c @@ -67,30 +67,13 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) extern int _creating_thread_lock; /* SDL_threads.c */ SDL_sem *sem; union semun init; - key_t key; sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); if ( sem == NULL ) { SDL_OutOfMemory(); return(NULL); } - /* This flag is true if we are creating the thread manager sem, - which is never freed. This allows us to reuse the same sem. - */ - if ( _creating_thread_lock ) { - key = 'S'+'D'+'L'; - } else { - key = IPC_PRIVATE; - } - /* Keep trying to create sem while we don't own the requested key */ - do { - if ( key != IPC_PRIVATE ) { - ++key; - } - sem->id = semget(key, 1, (0600|IPC_CREAT)); - } while ((sem->id < 0) && (key != IPC_PRIVATE) && (errno == EACCES)); - - /* Report the error if we eventually failed */ + sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT)); if ( sem->id < 0 ) { SDL_SetError("Couldn't create semaphore"); SDL_free(sem);