Index: src/libvortex.def =================================================================== --- src/libvortex.def (revision 3145) +++ src/libvortex.def (working copy) @@ -421,6 +421,7 @@ vortex_support_strtod vortex_support_unsetenv vortex_thread_create +vortex_thread_destroy vortex_thread_pool_being_closed vortex_thread_pool_exit vortex_thread_pool_get_num Index: src/vortex.c =================================================================== --- src/vortex.c (revision 3145) +++ src/vortex.c (working copy) @@ -768,7 +768,8 @@ thread_num); vortex_thread_pool_init (thread_num); - + __vortex_exit = false; + /* register the vortex exit function */ return true; } Index: src/vortex_reader.c =================================================================== --- src/vortex_reader.c (revision 3145) +++ src/vortex_reader.c (working copy) @@ -1283,6 +1283,7 @@ /* waiting until the reader is stoped */ vortex_async_queue_pop (vortex_reader_stopped); vortex_async_queue_unref (vortex_reader_stopped); + vortex_thread_destroy (&reader_thread, false); vortex_log (LOG_DOMAIN, VORTEX_LEVEL_DEBUG, "vortex reader process stopped"); Index: src/vortex_sequencer.c =================================================================== --- src/vortex_sequencer.c (revision 3145) +++ src/vortex_sequencer.c (working copy) @@ -501,6 +501,7 @@ /* wait until the sequencer stops */ vortex_async_queue_pop (vortex_sequencer_stoped); vortex_async_queue_unref (vortex_sequencer_stoped); + vortex_thread_destroy (&sequencer_thread, false); vortex_log (LOG_DOMAIN, VORTEX_LEVEL_DEBUG, "vortex sequencer completely stoped"); Index: src/vortex_thread.c =================================================================== --- src/vortex_thread.c (revision 3145) +++ src/vortex_thread.c (working copy) @@ -102,7 +102,9 @@ * * @return The function returns true if the thread was created * properly and the variable thread_def is defined with the particular - * thread reference created. + * thread reference created. + * + * @see vortex_thread_destroy */ bool vortex_thread_create (VortexThread * thread_def, VortexThreadFunc func, @@ -153,10 +155,11 @@ #if defined(AXL_OS_WIN32) /* windows implementation */ /* create the thread data to pass it to the proxy function */ - data = axl_new (VortexThreadData, 1); - data->func = func; - data->user_data = user_data; - (*thread_def) = (HANDLE) _beginthreadex ( + data = axl_new(VortexThreadData, 1); + data->func = func; + data->user_data = user_data; + thread_def->data = data; + thread_def->handle = (HANDLE) _beginthreadex ( /* use default SECURITY ATTRIBUTES */ NULL, /* use default stack size */ @@ -170,7 +173,7 @@ /* provide a reference that we will ignore */ &thread_id); - if ((*thread_def) == NULL) { + if (thread_def->handle == NULL) { /* free data because thread wasn't created */ axl_free (data); @@ -190,6 +193,7 @@ /* configure joinable state */ if (pthread_attr_setdetachstate (&attr, joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED) != 0) { vortex_log (LOG_DOMAIN, VORTEX_LEVEL_CRITICAL, "failed to configure detached state for the thread (pthread_attr_setdetachstate system call failed)"); + pthread_attr_destroy(&attr); return false; } /* end if */ @@ -199,6 +203,7 @@ /* function and user data */ func, user_data) != 0) { vortex_log (LOG_DOMAIN, VORTEX_LEVEL_CRITICAL, "unable to create the new thread (pthread_create system call failed)"); + pthread_attr_destroy(&attr); return false; } /* end if */ @@ -207,6 +212,72 @@ } /** + * @brief Wait for the provided thread to finish, destroy its + * resources and optionally release its pointer + * + * @param thread_def A reference to the thread that must be destroyed + * @param free_data Boolean that set whether the thread pointer + * should be released ot not + * + * @return true if the destroy operation was ok, otherwise false is + * returned. + */ +bool vortex_thread_destroy(VortexThread* thread_def, bool free_data) +{ +#if defined(AXL_OS_WIN32) + + DWORD err; + err = WaitForSingleObject(thread_def->handle, INFINITE); + switch( err ) + { + default: + case WAIT_OBJECT_0: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_DEBUG, "thread %p stopped", thread_def->handle); + break; + + case WAIT_ABANDONED: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_DEBUG, "unable to stop thread %p, wait_abandoned", thread_def->handle); + break; + + case WAIT_TIMEOUT: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_DEBUG, "unable to stop thread %p, wait_timeout", thread_def); + break; + } + CloseHandle(thread_def->handle); + axl_free(thread_def->data); + if( free_data ) axl_free(thread_def); + return err == WAIT_OBJECT_0; + +#elif defined(AXL_OS_UNIX) + + void* status; + int err = pthread_join(*thread_def, &status); + switch( err ) + { + default: + case 0: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_DEBUG, "thread %p stopped with status %p", thread_def, status); + break; + + case EINVAL: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_CRITICAL, "unable to stop non-joinable thread %p", thread_def); + break; + + case ESRCH: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_CRITICAL, "unable to stop invalid thread %p", thread_def); + break; + + case EDEADLK: + vortex_log(LOG_DOMAIN, VORTEX_LEVEL_CRITICAL, "unable to stop thread %p, deadlock detected", thread_def); + break; + } + if( free_data ) axl_free(thread_def); + return err == 0; + +#endif +} + +/** * @brief Allows to create a new mutex to protect critical sections to * be executed by several threads at the same time. * Index: src/vortex_thread.h =================================================================== --- src/vortex_thread.h (revision 3145) +++ src/vortex_thread.h (working copy) @@ -52,6 +52,8 @@ axlPointer user_data, ...); +bool vortex_thread_destroy (VortexThread * thread_def, bool free_data); + bool vortex_mutex_create (VortexMutex * mutex_def); bool vortex_mutex_destroy (VortexMutex * mutex_def); Index: src/vortex_thread_pool.c =================================================================== --- src/vortex_thread_pool.c (revision 3145) +++ src/vortex_thread_pool.c (working copy) @@ -121,7 +121,7 @@ VortexThread * thread = (VortexThread *) _thread; /* dealloc the node allocated */ - axl_free (thread); + vortex_thread_destroy (thread, true); return; } @@ -174,7 +174,7 @@ /* finish thread configuration */ VORTEX_THREAD_CONF_END)) { /* free the reference */ - axl_free (thread); + vortex_thread_destroy (thread, true); /* call to stop the thread pool */ vortex_thread_pool_exit (); Index: src/vortex_types.h =================================================================== --- src/vortex_types.h (revision 3145) +++ src/vortex_types.h (working copy) @@ -529,10 +529,15 @@ */ #if defined(AXL_OS_WIN32) -#define __OS_THREAD_TYPE__ HANDLE +#define __OS_THREAD_TYPE__ win32_thread_t #define __OS_MUTEX_TYPE__ HANDLE #define __OS_COND_TYPE__ win32_cond_t +typedef struct _win32_thread_t { + HANDLE handle; + void* data; +} win32_thread_t; + /** * @internal pthread_cond_t definition, fully based on the work done * by Dr. Schmidt. Take a look into his article (it is an excelent article):