mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Plug small memory leak when a thread exits.
Allow new threads to inherit scheduling policy. Use long instead of int in thread_exit, thanks to the ports maintainers for the heads up. svn path=/trunk/thread/; revision=5179
This commit is contained in:
parent
39ad755a25
commit
7e0894c0c9
@ -77,9 +77,6 @@ typedef struct thread_start_tag {
|
|||||||
void *(*start_routine)(void *);
|
void *(*start_routine)(void *);
|
||||||
void *arg;
|
void *arg;
|
||||||
|
|
||||||
/* whether to create the threaded in detached state */
|
|
||||||
int detached;
|
|
||||||
|
|
||||||
/* the other stuff we need to make sure this thread is inserted into
|
/* the other stuff we need to make sure this thread is inserted into
|
||||||
** the thread tree
|
** the thread tree
|
||||||
*/
|
*/
|
||||||
@ -126,7 +123,6 @@ static int _free_mutex(void *key);
|
|||||||
|
|
||||||
static int _compare_threads(void *compare_arg, void *a, void *b);
|
static int _compare_threads(void *compare_arg, void *a, void *b);
|
||||||
static int _free_thread(void *key);
|
static int _free_thread(void *key);
|
||||||
static int _free_thread_if_detached(void *key);
|
|
||||||
|
|
||||||
/* mutex fuctions */
|
/* mutex fuctions */
|
||||||
static void _mutex_create(mutex_t *mutex);
|
static void _mutex_create(mutex_t *mutex);
|
||||||
@ -267,44 +263,58 @@ static void _catch_signals(void)
|
|||||||
thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
|
thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
|
||||||
void *arg, int detached, int line, char *file)
|
void *arg, int detached, int line, char *file)
|
||||||
{
|
{
|
||||||
int created;
|
int ok = 1;
|
||||||
thread_type *thread;
|
thread_type *thread = NULL;
|
||||||
thread_start_t *start;
|
thread_start_t *start = NULL;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
|
thread = (thread_type *)calloc(1, sizeof(thread_type));
|
||||||
|
do {
|
||||||
|
if (thread == NULL)
|
||||||
|
break;
|
||||||
|
start = (thread_start_t *)calloc(1, sizeof(thread_start_t));
|
||||||
|
if (start == NULL)
|
||||||
|
break;
|
||||||
|
if (pthread_attr_init (&attr) < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
thread = (thread_type *)malloc(sizeof(thread_type));
|
|
||||||
start = (thread_start_t *)malloc(sizeof(thread_start_t));
|
|
||||||
thread->line = line;
|
thread->line = line;
|
||||||
thread->file = strdup(file);
|
thread->file = strdup(file);
|
||||||
|
|
||||||
_mutex_lock(&_threadtree_mutex);
|
_mutex_lock (&_threadtree_mutex);
|
||||||
thread->thread_id = _next_thread_id++;
|
thread->thread_id = _next_thread_id++;
|
||||||
_mutex_unlock(&_threadtree_mutex);
|
_mutex_unlock (&_threadtree_mutex);
|
||||||
|
|
||||||
thread->name = strdup(name);
|
thread->name = strdup(name);
|
||||||
thread->create_time = time(NULL);
|
thread->create_time = time(NULL);
|
||||||
thread->detached = 0;
|
|
||||||
|
|
||||||
start->start_routine = start_routine;
|
start->start_routine = start_routine;
|
||||||
start->arg = arg;
|
start->arg = arg;
|
||||||
start->thread = thread;
|
start->thread = thread;
|
||||||
start->detached = detached;
|
|
||||||
|
|
||||||
created = 0;
|
pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED);
|
||||||
if (pthread_create(&thread->sys_thread, NULL, _start_routine, start) == 0)
|
if (detached)
|
||||||
created = 1;
|
{
|
||||||
#ifdef THREAD_DEBUG
|
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
|
||||||
else
|
thread->detached = 1;
|
||||||
LOG_ERROR("Could not create new thread");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (created == 0) {
|
|
||||||
#ifdef THREAD_DEBUG
|
|
||||||
LOG_ERROR("System won't let me create more threads, giving up");
|
|
||||||
#endif
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pthread_create (&thread->sys_thread, &attr, _start_routine, start) == 0)
|
||||||
|
{
|
||||||
|
pthread_attr_destroy (&attr);
|
||||||
return thread;
|
return thread;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pthread_attr_destroy (&attr);
|
||||||
|
}
|
||||||
|
while (0);
|
||||||
|
|
||||||
|
#ifdef THREAD_DEBUG
|
||||||
|
LOG_ERROR("Could not create new thread %s", name);
|
||||||
|
#endif
|
||||||
|
if (start) free (start);
|
||||||
|
if (thread) free (thread);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _mutex_create
|
/* _mutex_create
|
||||||
@ -547,7 +557,7 @@ void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file)
|
|||||||
pthread_rwlock_unlock(&rwlock->sys_rwlock);
|
pthread_rwlock_unlock(&rwlock->sys_rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_exit_c(int val, int line, char *file)
|
void thread_exit_c(long val, int line, char *file)
|
||||||
{
|
{
|
||||||
thread_type *th = thread_self();
|
thread_type *th = thread_self();
|
||||||
|
|
||||||
@ -574,17 +584,18 @@ void thread_exit_c(int val, int line, char *file)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (th) {
|
if (th && th->detached)
|
||||||
|
{
|
||||||
#ifdef THREAD_DEBUG
|
#ifdef THREAD_DEBUG
|
||||||
LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line);
|
LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_mutex_lock(&_threadtree_mutex);
|
_mutex_lock(&_threadtree_mutex);
|
||||||
avl_delete(_threadtree, th, _free_thread_if_detached);
|
avl_delete(_threadtree, th, _free_thread);
|
||||||
_mutex_unlock(&_threadtree_mutex);
|
_mutex_unlock(&_threadtree_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_exit((void *)val);
|
pthread_exit ((void*)val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sleep for a number of microseconds */
|
/* sleep for a number of microseconds */
|
||||||
@ -625,12 +636,9 @@ static void *_start_routine(void *arg)
|
|||||||
void *(*start_routine)(void *) = start->start_routine;
|
void *(*start_routine)(void *) = start->start_routine;
|
||||||
void *real_arg = start->arg;
|
void *real_arg = start->arg;
|
||||||
thread_type *thread = start->thread;
|
thread_type *thread = start->thread;
|
||||||
int detach = start->detached;
|
|
||||||
|
|
||||||
_block_signals();
|
_block_signals();
|
||||||
|
|
||||||
free(start);
|
|
||||||
|
|
||||||
/* insert thread into thread tree here */
|
/* insert thread into thread tree here */
|
||||||
_mutex_lock(&_threadtree_mutex);
|
_mutex_lock(&_threadtree_mutex);
|
||||||
thread->sys_thread = pthread_self();
|
thread->sys_thread = pthread_self();
|
||||||
@ -641,20 +649,17 @@ static void *_start_routine(void *arg)
|
|||||||
LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line);
|
LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (detach) {
|
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
pthread_detach(thread->sys_thread);
|
free (start);
|
||||||
thread->detached = 1;
|
|
||||||
}
|
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
|
||||||
|
|
||||||
/* call the real start_routine and start the thread
|
|
||||||
** this should never exit!
|
|
||||||
*/
|
|
||||||
(start_routine)(real_arg);
|
(start_routine)(real_arg);
|
||||||
|
|
||||||
#ifdef THREAD_DEBUG
|
if (thread->detached)
|
||||||
LOG_WARN("Thread x should never exit from here!!!");
|
{
|
||||||
#endif
|
_mutex_lock (&_threadtree_mutex);
|
||||||
|
avl_delete (_threadtree, thread, _free_thread);
|
||||||
|
_mutex_unlock (&_threadtree_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -805,21 +810,4 @@ static int _free_thread(void *key)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _free_thread_if_detached(void *key)
|
|
||||||
{
|
|
||||||
thread_type *t = key;
|
|
||||||
if(t->detached)
|
|
||||||
return _free_thread(key);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file);
|
|||||||
void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file);
|
void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file);
|
||||||
void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file);
|
void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file);
|
||||||
void thread_rwlock_destroy(rwlock_t *rwlock);
|
void thread_rwlock_destroy(rwlock_t *rwlock);
|
||||||
void thread_exit_c(int val, int line, char *file);
|
void thread_exit_c(long val, int line, char *file);
|
||||||
|
|
||||||
/* sleeping */
|
/* sleeping */
|
||||||
void thread_sleep(unsigned long len);
|
void thread_sleep(unsigned long len);
|
||||||
|
Loading…
Reference in New Issue
Block a user