@ -256,7 +256,8 @@ struct agent_pvt {
char name [ AST_MAX_AGENT ] ;
int inherited_devicestate ; /*!< Does the underlying channel have a devicestate to pass? */
ast_mutex_t app_lock ; /**< Synchronization between owning applications */
volatile pthread_t owning_app ; /**< Owning application thread id */
int app_lock_flag ;
ast_cond_t app_complete_cond ;
volatile int app_sleep_cond ; /**< Sleep condition for the login app */
struct ast_channel * owner ; /**< Agent */
char loginchan [ 80 ] ; /**< channel they logged in from */
@ -451,7 +452,8 @@ static struct agent_pvt *add_agent(const char *agent, int pending)
ast_copy_string ( p - > agent , agt , sizeof ( p - > agent ) ) ;
ast_mutex_init ( & p - > lock ) ;
ast_mutex_init ( & p - > app_lock ) ;
p - > owning_app = ( pthread_t ) - 1 ;
ast_cond_init ( & p - > app_complete_cond , NULL ) ;
p - > app_lock_flag = 0 ;
p - > app_sleep_cond = 1 ;
p - > group = group ;
p - > pending = pending ;
@ -509,12 +511,14 @@ static int agent_cleanup(struct agent_pvt *p)
chan - > tech_pvt = NULL ;
p - > app_sleep_cond = 1 ;
/* Release ownership of the agent to other threads (presumably running the login app). */
ast_mutex_unlock ( & p - > app_lock ) ;
p - > app_lock_flag = 0 ;
ast_cond_signal ( & p - > app_complete_cond ) ;
if ( chan )
ast_channel_free ( chan ) ;
if ( p - > dead ) {
ast_mutex_destroy ( & p - > lock ) ;
ast_mutex_destroy ( & p - > app_lock ) ;
ast_cond_destroy ( & p - > app_complete_cond ) ;
ast_free ( p ) ;
}
return 0 ;
@ -1001,6 +1005,7 @@ static int agent_hangup(struct ast_channel *ast)
} else if ( p - > dead ) {
ast_mutex_destroy ( & p - > lock ) ;
ast_mutex_destroy ( & p - > app_lock ) ;
ast_cond_destroy ( & p - > app_complete_cond ) ;
ast_free ( p ) ;
} else {
if ( p - > chan ) {
@ -1011,8 +1016,10 @@ static int agent_hangup(struct ast_channel *ast)
ast_mutex_unlock ( & p - > lock ) ;
}
/* Release ownership of the agent to other threads (presumably running the login app). */
if ( ast_strlen_zero ( p - > loginchan ) )
ast_mutex_unlock ( & p - > app_lock ) ;
if ( ast_strlen_zero ( p - > loginchan ) ) {
p - > app_lock_flag = 0 ;
ast_cond_signal ( & p - > app_complete_cond ) ;
}
}
return 0 ;
}
@ -1099,6 +1106,7 @@ static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct
static struct ast_channel * agent_new ( struct agent_pvt * p , int state )
{
struct ast_channel * tmp ;
int alreadylocked ;
#if 0
if ( ! p - > chan ) {
ast_log ( LOG_WARNING , " No channel? :( \n " ) ;
@ -1144,11 +1152,15 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
* implemented in the kernel for this .
*/
p - > app_sleep_cond = 0 ;
if ( ast_strlen_zero ( p - > loginchan ) & & ast_mutex_trylock ( & p - > app_lock ) ) {
alreadylocked = p - > app_lock_flag ;
p - > app_lock_flag = 1 ;
if ( ast_strlen_zero ( p - > loginchan ) & & alreadylocked ) {
if ( p - > chan ) {
ast_queue_frame ( p - > chan , & ast_null_frame ) ;
ast_mutex_unlock ( & p - > lock ) ; /* For other thread to read the condition. */
ast_mutex_lock ( & p - > app_lock ) ;
p - > app_lock_flag = 1 ;
ast_mutex_lock ( & p - > lock ) ;
} else {
ast_log ( LOG_WARNING , " Agent disconnected while we were connecting the call \n " ) ;
@ -1157,7 +1169,8 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
p - > app_sleep_cond = 1 ;
ast_channel_free ( tmp ) ;
ast_mutex_unlock ( & p - > lock ) ; /* For other thread to read the condition. */
ast_mutex_unlock ( & p - > app_lock ) ;
p - > app_lock_flag = 0 ;
ast_cond_signal ( & p - > app_complete_cond ) ;
return NULL ;
}
} else if ( ! ast_strlen_zero ( p - > loginchan ) ) {
@ -1175,14 +1188,6 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
}
if ( p - > chan )
ast_indicate ( p - > chan , AST_CONTROL_UNHOLD ) ;
p - > owning_app = pthread_self ( ) ;
/* After the above step, there should not be any blockers. */
if ( p - > chan ) {
if ( ast_test_flag ( p - > chan , AST_FLAG_BLOCKING ) ) {
ast_log ( LOG_ERROR , " A blocker exists after agent channel ownership acquired \n " ) ;
ast_assert ( ast_test_flag ( p - > chan , AST_FLAG_BLOCKING ) = = 0 ) ;
}
}
return tmp ;
}
@ -1347,6 +1352,7 @@ static int read_agent_config(int reload)
if ( ! p - > chan ) {
ast_mutex_destroy ( & p - > lock ) ;
ast_mutex_destroy ( & p - > app_lock ) ;
ast_cond_destroy ( & p - > app_complete_cond ) ;
ast_free ( p ) ;
} else {
/* Cause them to hang up */
@ -2233,15 +2239,17 @@ static int login_exec(struct ast_channel *chan, void *data)
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
/* Synchronize channel ownership between call to agent and itself. */
ast_mutex_lock ( & p - > app_lock ) ;
ast_mutex_lock ( & p - > app_lock ) ;
if ( p - > app_lock_flag = = 1 ) {
ast_cond_wait ( & p - > app_complete_cond , & p - > app_lock ) ;
}
ast_mutex_unlock ( & p - > app_lock ) ;
ast_mutex_lock ( & p - > lock ) ;
p - > owning_app = pthread_self ( ) ;
ast_mutex_unlock ( & p - > lock ) ;
if ( p - > ackcall > 1 )
res = agent_ack_sleep ( p ) ;
else
res = ast_safe_sleep_conditional ( chan , 1000 , agent_cont_sleep , p ) ;
ast_mutex_unlock ( & p - > app_lock ) ;
if ( ( p - > ackcall > 1 ) & & ( res = = 1 ) ) {
AST_LIST_LOCK ( & agents ) ;
ast_mutex_lock ( & p - > lock ) ;
@ -2276,6 +2284,7 @@ static int login_exec(struct ast_channel *chan, void *data)
if ( p - > dead & & ! p - > owner ) {
ast_mutex_destroy ( & p - > lock ) ;
ast_mutex_destroy ( & p - > app_lock ) ;
ast_cond_destroy ( & p - > app_complete_cond ) ;
ast_free ( p ) ;
}
}