Review Board 1.7.16


IAX2, prevent network thread starting before all helper threads are ready

Review Request #2427 - Created April 5, 2013 and submitted

Alec Davis
1.8 to trunk
ASTERISK-18827
Reviewers
asterisk-dev
Asterisk
If the first network message was received before iax2_process_thread() was sleeping, the thread would go to sleep, and sleep forever, with deferred frames banking up.

start_network_thread() creates the initial helper threads and the network_thread at the same time (near enough), with no checks that the helper threads were ready before the network thread was created.

Each iax2_process_thread() is required to be at 'ast_cond_wait(&thread->cond, &thread->lock)' before any messages can be accepted.
To achieve this, only start the network_thread after each of the helper threads is ready.

The fix is the same method as find_idle_thread() uses when an iax dynamic thread is created, that then waits for the init_cond to be satisfied.
Prior to fix, iax show threads had thread 1 never finishing, with actions = 0, which means it never got processed.
...
Thread 10: state=0, update=6, actions=1, func=''
Active Threads:
Thread P1: state=1, update=1365045454, actions=0, func='socket_process'
Dynamic Threads:
10 of 10 threads accounted for with 0 dynamic threads

after fix, works as expected.

Diff revision 1 (Latest)

  1. trunk/channels/chan_iax2.c: Loading...
trunk/channels/chan_iax2.c
Revision 376441 New Change
[20] 12399 lines
[+20] [+] static int start_network_thread(void)
12400
			thread->threadnum = ++threadcount;
12400
			thread->threadnum = ++threadcount;
12401
			ast_mutex_init(&thread->lock);
12401
			ast_mutex_init(&thread->lock);
12402
			ast_cond_init(&thread->cond, NULL);
12402
			ast_cond_init(&thread->cond, NULL);
12403
			ast_mutex_init(&thread->init_lock);
12403
			ast_mutex_init(&thread->init_lock);
12404
			ast_cond_init(&thread->init_cond, NULL);
12404
			ast_cond_init(&thread->init_cond, NULL);

    
   
12405

   

    
   
12406
			ast_mutex_lock(&thread->init_lock);

    
   
12407

   
12405
			if (ast_pthread_create_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
12408
			if (ast_pthread_create_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
12406
				ast_log(LOG_WARNING, "Failed to create new thread!\n");
12409
				ast_log(LOG_WARNING, "Failed to create new thread!\n");
12407
				ast_mutex_destroy(&thread->lock);
12410
				ast_mutex_destroy(&thread->lock);
12408
				ast_cond_destroy(&thread->cond);
12411
				ast_cond_destroy(&thread->cond);

    
   
12412
				ast_mutex_unlock(&thread->init_lock);
12409
				ast_mutex_destroy(&thread->init_lock);
12413
				ast_mutex_destroy(&thread->init_lock);
12410
				ast_cond_destroy(&thread->init_cond);
12414
				ast_cond_destroy(&thread->init_cond);
12411
				ast_free(thread);
12415
				ast_free(thread);
12412
				thread = NULL;
12416
				thread = NULL;
12413
				continue;
12417
				continue;
12414
			}
12418
			}

    
   
12419
			/* Wait for the thread to be ready */

    
   
12420
			ast_cond_wait(&thread->init_cond, &thread->init_lock);

    
   
12421

   

    
   
12422
			/* Done with init_lock */

    
   
12423
			ast_mutex_unlock(&thread->init_lock);

    
   
12424

   
12415
			AST_LIST_LOCK(&idle_list);
12425
			AST_LIST_LOCK(&idle_list);
12416
			AST_LIST_INSERT_TAIL(&idle_list, thread, list);
12426
			AST_LIST_INSERT_TAIL(&idle_list, thread, list);
12417
			AST_LIST_UNLOCK(&idle_list);
12427
			AST_LIST_UNLOCK(&idle_list);
12418
		}
12428
		}
12419
	}
12429
	}
[+20] [20] 2641 lines
  1. trunk/channels/chan_iax2.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.