@ -1026,6 +1026,7 @@ struct iax2_thread {
* a call which this thread is already processing a full frame for , they
* are queued up here . */
AST_LIST_HEAD_NOLOCK ( , iax2_pkt_buf ) full_frames ;
unsigned char stop ;
} ;
/* Thread lists */
@ -1351,7 +1352,7 @@ static struct iax2_thread *find_idle_thread(void)
ast_mutex_lock ( & thread - > init_lock ) ;
/* Create thread and send it on it's way */
if ( ast_pthread_create_ detached_ background( & thread - > threadid , NULL , iax2_process_thread , thread ) ) {
if ( ast_pthread_create_ background( & thread - > threadid , NULL , iax2_process_thread , thread ) ) {
ast_cond_destroy ( & thread - > cond ) ;
ast_mutex_destroy ( & thread - > lock ) ;
ast_free ( thread ) ;
@ -11383,13 +11384,22 @@ static void *iax2_process_thread(void *data)
struct timespec ts ;
int put_into_idle = 0 ;
int first_time = 1 ;
int old_state ;
ast_atomic_fetchadd_int ( & iaxactivethreadcount , 1 ) ;
ast_atomic_fetchadd_int ( & iaxactivethreadcount , 1 ) ;
pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE , & old_state ) ;
pthread_cleanup_push ( iax2_process_thread_cleanup , data ) ;
for ( ; ; ) {
for ( ; ; ) {
/* Wait for something to signal us to be awake */
ast_mutex_lock ( & thread - > lock ) ;
if ( thread - > stop ) {
ast_mutex_unlock ( & thread - > lock ) ;
break ;
}
/* Flag that we're ready to accept signals */
if ( first_time ) {
signal_condition ( & thread - > init_lock , & thread - > init_cond ) ;
@ -11397,8 +11407,9 @@ static void *iax2_process_thread(void *data)
}
/* Put into idle list if applicable */
if ( put_into_idle )
if ( put_into_idle ) {
insert_idle_thread ( thread ) ;
}
if ( thread - > type = = IAX_THREAD_TYPE_DYNAMIC ) {
struct iax2_thread * t = NULL ;
@ -11409,7 +11420,7 @@ static void *iax2_process_thread(void *data)
if ( ast_cond_timedwait ( & thread - > cond , & thread - > lock , & ts ) = = ETIMEDOUT ) {
/* This thread was never put back into the available dynamic
* thread list , so just go away . */
if ( ! put_into_idle ) {
if ( ! put_into_idle | | thread - > stop ) {
ast_mutex_unlock ( & thread - > lock ) ;
break ;
}
@ -11431,8 +11442,7 @@ static void *iax2_process_thread(void *data)
wait = ast_tvadd ( ast_tvnow ( ) , ast_samp2tv ( 30000 , 1000 ) ) ;
ts . tv_sec = wait . tv_sec ;
ts . tv_nsec = wait . tv_usec * 1000 ;
if ( ast_cond_timedwait ( & thread - > cond , & thread - > lock , & ts ) = = ETIMEDOUT )
{
if ( ast_cond_timedwait ( & thread - > cond , & thread - > lock , & ts ) = = ETIMEDOUT ) {
ast_mutex_unlock ( & thread - > lock ) ;
break ;
}
@ -11446,11 +11456,15 @@ static void *iax2_process_thread(void *data)
ast_mutex_unlock ( & thread - > lock ) ;
if ( thread - > stop ) {
break ;
}
if ( thread - > iostate = = IAX_IOSTATE_IDLE )
continue ;
/* See what we need to do */
switch ( thread - > iostate ) {
switch ( thread - > iostate ) {
case IAX_IOSTATE_READY :
thread - > actions + + ;
thread - > iostate = IAX_IOSTATE_PROCESSING ;
@ -11906,7 +11920,7 @@ static int start_network_thread(void)
thread - > threadnum = + + threadcount ;
ast_mutex_init ( & thread - > lock ) ;
ast_cond_init ( & thread - > cond , NULL ) ;
if ( ast_pthread_create_ detache d( & thread - > threadid , NULL , iax2_process_thread , thread ) ) {
if ( ast_pthread_create_ backgroun d( & thread - > threadid , NULL , iax2_process_thread , thread ) ) {
ast_log ( LOG_WARNING , " Failed to create new thread! \n " ) ;
ast_free ( thread ) ;
thread = NULL ;
@ -13838,55 +13852,62 @@ static struct ast_cli_entry cli_iax2[] = {
# endif /* IAXTESTS */
} ;
static void cleanup_thread_list ( void * head )
{
AST_LIST_HEAD ( iax2_thread_list , iax2_thread ) ;
struct iax2_thread_list * list_head = head ;
struct iax2_thread * thread ;
AST_LIST_LOCK ( list_head ) ;
while ( ( thread = AST_LIST_REMOVE_HEAD ( & idle_list , list ) ) ) {
pthread_t thread_id = thread - > threadid ;
thread - > stop = 1 ;
signal_condition ( & thread - > lock , & thread - > cond ) ;
AST_LIST_UNLOCK ( list_head ) ;
pthread_join ( thread_id , NULL ) ;
AST_LIST_LOCK ( list_head ) ;
}
AST_LIST_UNLOCK ( list_head ) ;
}
static int __unload_module ( void )
{
struct iax2_thread * thread = NULL ;
struct ast_context * con ;
int x ;
ast_manager_unregister ( " IAXpeers " ) ;
ast_manager_unregister ( " IAXpeerlist " ) ;
ast_manager_unregister ( " IAXnetstats " ) ;
ast_manager_unregister ( " IAXregistry " ) ;
ast_unregister_application ( papp ) ;
ast_cli_unregister_multiple ( cli_iax2 , ARRAY_LEN ( cli_iax2 ) ) ;
ast_unregister_switch ( & iax2_switch ) ;
ast_channel_unregister ( & iax2_tech ) ;
if ( netthreadid ! = AST_PTHREADT_NULL ) {
pthread_cancel ( netthreadid ) ;
pthread_kill ( netthreadid , SIGURG ) ;
pthread_join ( netthreadid , NULL ) ;
}
sched = ast_sched_thread_destroy ( sched ) ;
for ( x = 0 ; x < ARRAY_LEN ( iaxs ) ; x + + ) {
if ( iaxs [ x ] ) {
iax2_destroy ( x ) ;
}
}
/* Call for all threads to halt */
AST_LIST_LOCK ( & idle_list ) ;
while ( ( thread = AST_LIST_REMOVE_HEAD ( & idle_list , list ) ) )
pthread_cancel ( thread - > threadid ) ;
AST_LIST_UNLOCK ( & idle_list ) ;
AST_LIST_LOCK ( & active_list ) ;
while ( ( thread = AST_LIST_REMOVE_HEAD ( & active_list , list ) ) )
pthread_cancel ( thread - > threadid ) ;
AST_LIST_UNLOCK ( & active_list ) ;
AST_LIST_LOCK ( & dynamic_list ) ;
while ( ( thread = AST_LIST_REMOVE_HEAD ( & dynamic_list , list ) ) )
pthread_cancel ( thread - > threadid ) ;
AST_LIST_UNLOCK ( & dynamic_list ) ;
cleanup_thread_list ( & idle_list ) ;
cleanup_thread_list ( & active_list ) ;
cleanup_thread_list ( & dynamic_list ) ;
/* Wait for threads to exit */
while ( 0 < iaxactivethreadcount )
usleep ( 10000 ) ;
sched = ast_sched_thread_destroy ( sched ) ;
ast_netsock_release ( netsock ) ;
ast_netsock_release ( outsock ) ;
for ( x = 0 ; x < ARRAY_LEN ( iaxs ) ; x + + ) {
if ( iaxs [ x ] ) {
iax2_destroy ( x ) ;
}
}
ast_manager_unregister ( " IAXpeers " ) ;
ast_manager_unregister ( " IAXpeerlist " ) ;
ast_manager_unregister ( " IAXnetstats " ) ;
ast_manager_unregister ( " IAXregistry " ) ;
ast_unregister_application ( papp ) ;
ast_cli_unregister_multiple ( cli_iax2 , ARRAY_LEN ( cli_iax2 ) ) ;
ast_unregister_switch ( & iax2_switch ) ;
ast_channel_unregister ( & iax2_tech ) ;
delete_users ( ) ;
iax_provision_unload ( ) ;
reload_firmware ( 1 ) ;