Commit fa0e2110 authored by Sam Lantinga's avatar Sam Lantinga

Fixed bug #150

memory leak in SDL_thread.c

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401503
parent ee03e101
...@@ -37,20 +37,13 @@ static int SDL_maxthreads = 0; ...@@ -37,20 +37,13 @@ static int SDL_maxthreads = 0;
static int SDL_numthreads = 0; static int SDL_numthreads = 0;
static SDL_Thread **SDL_Threads = NULL; static SDL_Thread **SDL_Threads = NULL;
static SDL_mutex *thread_lock = NULL; static SDL_mutex *thread_lock = NULL;
int _creating_thread_lock = 0;
int SDL_ThreadsInit(void) int SDL_ThreadsInit(void)
{ {
int retval; int retval;
retval = 0; 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(); thread_lock = SDL_CreateMutex();
_creating_thread_lock = 0;
if ( thread_lock == NULL ) { if ( thread_lock == NULL ) {
retval = -1; retval = -1;
} }
...@@ -76,15 +69,13 @@ void SDL_ThreadsQuit() ...@@ -76,15 +69,13 @@ void SDL_ThreadsQuit()
/* Routines for manipulating the thread list */ /* Routines for manipulating the thread list */
static void SDL_AddThread(SDL_Thread *thread) static void SDL_AddThread(SDL_Thread *thread)
{ {
SDL_Thread **threads;
/* WARNING: /* WARNING:
If the very first threads are created simultaneously, then If the very first threads are created simultaneously, then
there could be a race condition causing memory corruption. there could be a race condition causing memory corruption.
In practice, this isn't a problem because by definition there In practice, this isn't a problem because by definition there
is only one thread running the first time this is called. is only one thread running the first time this is called.
*/ */
if ( thread_lock == NULL ) { if ( !thread_lock ) {
if ( SDL_ThreadsInit() < 0 ) { if ( SDL_ThreadsInit() < 0 ) {
return; return;
} }
...@@ -97,17 +88,14 @@ static void SDL_AddThread(SDL_Thread *thread) ...@@ -97,17 +88,14 @@ static void SDL_AddThread(SDL_Thread *thread)
SDL_numthreads, SDL_maxthreads); SDL_numthreads, SDL_maxthreads);
#endif #endif
if ( SDL_numthreads == SDL_maxthreads ) { if ( SDL_numthreads == SDL_maxthreads ) {
threads=(SDL_Thread **)SDL_malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)* SDL_Thread **threads;
(sizeof *threads)); threads = (SDL_Thread **)SDL_realloc(SDL_Threads,
(SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads));
if ( threads == NULL ) { if ( threads == NULL ) {
SDL_OutOfMemory(); SDL_OutOfMemory();
goto done; goto done;
} }
SDL_memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads));
SDL_maxthreads += ARRAY_CHUNKSIZE; SDL_maxthreads += ARRAY_CHUNKSIZE;
if ( SDL_Threads ) {
SDL_free(SDL_Threads);
}
SDL_Threads = threads; SDL_Threads = threads;
} }
SDL_Threads[SDL_numthreads++] = thread; SDL_Threads[SDL_numthreads++] = thread;
...@@ -119,30 +107,35 @@ static void SDL_DelThread(SDL_Thread *thread) ...@@ -119,30 +107,35 @@ static void SDL_DelThread(SDL_Thread *thread)
{ {
int i; int i;
if ( thread_lock ) { if ( !thread_lock ) {
SDL_mutexP(thread_lock); return;
for ( i=0; i<SDL_numthreads; ++i ) { }
if ( thread == SDL_Threads[i] ) { SDL_mutexP(thread_lock);
break; for ( i=0; i<SDL_numthreads; ++i ) {
} if ( thread == SDL_Threads[i] ) {
break;
} }
if ( i < SDL_numthreads ) { }
if ( --SDL_numthreads > 0 ) { if ( i < SDL_numthreads ) {
while ( i < SDL_numthreads ) { if ( --SDL_numthreads > 0 ) {
SDL_Threads[i] = SDL_Threads[i+1]; while ( i < SDL_numthreads ) {
++i; SDL_Threads[i] = SDL_Threads[i+1];
} ++i;
} else {
SDL_maxthreads = 0;
SDL_free(SDL_Threads);
SDL_Threads = NULL;
} }
} else {
SDL_maxthreads = 0;
SDL_free(SDL_Threads);
SDL_Threads = NULL;
}
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Deleting thread (%d left - %d max)\n", printf("Deleting thread (%d left - %d max)\n",
SDL_numthreads, SDL_maxthreads); SDL_numthreads, SDL_maxthreads);
#endif #endif
} }
SDL_mutexV(thread_lock); SDL_mutexV(thread_lock);
if ( SDL_Threads == NULL ) {
SDL_ThreadsQuit();
} }
} }
......
...@@ -67,30 +67,13 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) ...@@ -67,30 +67,13 @@ SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
extern int _creating_thread_lock; /* SDL_threads.c */ extern int _creating_thread_lock; /* SDL_threads.c */
SDL_sem *sem; SDL_sem *sem;
union semun init; union semun init;
key_t key;
sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
if ( sem == NULL ) { if ( sem == NULL ) {
SDL_OutOfMemory(); SDL_OutOfMemory();
return(NULL); return(NULL);
} }
/* This flag is true if we are creating the thread manager sem, sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
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 */
if ( sem->id < 0 ) { if ( sem->id < 0 ) {
SDL_SetError("Couldn't create semaphore"); SDL_SetError("Couldn't create semaphore");
SDL_free(sem); SDL_free(sem);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment