@ -864,17 +864,32 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
}
}
# if defined(REF_DEBUG)
# if defined(REF_DEBUG)
if ( ! ( tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_channel_destructor , " " , file , line , function , 1 ) ) ) {
tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_channel_destructor , " " , file , line ,
return NULL ;
function , 1 ) ;
}
# elif defined(__AST_DEBUG_MALLOC)
# elif defined(__AST_DEBUG_MALLOC)
if ( ! ( tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_channel_destructor , " " , file , line , function , 0 ) ) ) {
tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_channel_destructor , " " , file , line ,
return NULL ;
function , 0 ) ;
}
# else
# else
if ( ! ( tmp = ao2_alloc ( sizeof ( * tmp ) , ast_channel_destructor ) ) ) {
tmp = ao2_alloc ( sizeof ( * tmp ) , ast_channel_destructor ) ;
# endif
if ( ! tmp ) {
/* Channel structure allocation failure. */
return NULL ;
return NULL ;
}
}
/*
* Init file descriptors to unopened state so
* the destructor can know not to close them .
*/
tmp - > timingfd = - 1 ;
for ( x = 0 ; x < ARRAY_LEN ( tmp - > alertpipe ) ; + + x ) {
tmp - > alertpipe [ x ] = - 1 ;
}
for ( x = 0 ; x < ARRAY_LEN ( tmp - > fds ) ; + + x ) {
tmp - > fds [ x ] = - 1 ;
}
# ifdef HAVE_EPOLL
tmp - > epfd = epoll_create ( 25 ) ;
# endif
# endif
if ( ! ( tmp - > sched = sched_context_create ( ) ) ) {
if ( ! ( tmp - > sched = sched_context_create ( ) ) ) {
@ -882,10 +897,6 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
return ast_channel_unref ( tmp ) ;
return ast_channel_unref ( tmp ) ;
}
}
if ( ( ast_string_field_init ( tmp , 128 ) ) ) {
return ast_channel_unref ( tmp ) ;
}
if ( cid_name ) {
if ( cid_name ) {
if ( ! ( tmp - > cid . cid_name = ast_strdup ( cid_name ) ) ) {
if ( ! ( tmp - > cid . cid_name = ast_strdup ( cid_name ) ) ) {
return ast_channel_unref ( tmp ) ;
return ast_channel_unref ( tmp ) ;
@ -897,62 +908,44 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
}
}
}
}
# ifdef HAVE_EPOLL
tmp - > epfd = epoll_create ( 25 ) ;
# endif
for ( x = 0 ; x < AST_MAX_FDS ; x + + ) {
tmp - > fds [ x ] = - 1 ;
# ifdef HAVE_EPOLL
tmp - > epfd_data [ x ] = NULL ;
# endif
}
if ( ( tmp - > timer = ast_timer_open ( ) ) ) {
if ( ( tmp - > timer = ast_timer_open ( ) ) ) {
needqueue = 0 ;
needqueue = 0 ;
tmp - > timingfd = ast_timer_fd ( tmp - > timer ) ;
tmp - > timingfd = ast_timer_fd ( tmp - > timer ) ;
} else {
tmp - > timingfd = - 1 ;
}
}
if ( needqueue ) {
if ( needqueue ) {
if ( pipe ( tmp - > alertpipe ) ) {
if ( pipe ( tmp - > alertpipe ) ) {
ast_log ( LOG_WARNING , " Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n \n " ) ;
ast_log ( LOG_WARNING , " Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n \n " ) ;
alertpipe_failed :
return ast_channel_unref ( tmp ) ;
if ( tmp - > timer ) {
ast_timer_close ( tmp - > timer ) ;
}
sched_context_destroy ( tmp - > sched ) ;
ast_string_field_free_memory ( tmp ) ;
ast_free ( tmp - > cid . cid_name ) ;
ast_free ( tmp - > cid . cid_num ) ;
ast_free ( tmp ) ;
return NULL ;
} else {
} else {
flags = fcntl ( tmp - > alertpipe [ 0 ] , F_GETFL ) ;
flags = fcntl ( tmp - > alertpipe [ 0 ] , F_GETFL ) ;
if ( fcntl ( tmp - > alertpipe [ 0 ] , F_SETFL , flags | O_NONBLOCK ) < 0 ) {
if ( fcntl ( tmp - > alertpipe [ 0 ] , F_SETFL , flags | O_NONBLOCK ) < 0 ) {
ast_log ( LOG_WARNING , " Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s) \n " , errno , strerror ( errno ) ) ;
ast_log ( LOG_WARNING , " Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s) \n " , errno , strerror ( errno ) ) ;
close ( tmp - > alertpipe [ 0 ] ) ;
return ast_channel_unref ( tmp ) ;
close ( tmp - > alertpipe [ 1 ] ) ;
goto alertpipe_failed ;
}
}
flags = fcntl ( tmp - > alertpipe [ 1 ] , F_GETFL ) ;
flags = fcntl ( tmp - > alertpipe [ 1 ] , F_GETFL ) ;
if ( fcntl ( tmp - > alertpipe [ 1 ] , F_SETFL , flags | O_NONBLOCK ) < 0 ) {
if ( fcntl ( tmp - > alertpipe [ 1 ] , F_SETFL , flags | O_NONBLOCK ) < 0 ) {
ast_log ( LOG_WARNING , " Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s) \n " , errno , strerror ( errno ) ) ;
ast_log ( LOG_WARNING , " Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s) \n " , errno , strerror ( errno ) ) ;
close ( tmp - > alertpipe [ 0 ] ) ;
return ast_channel_unref ( tmp ) ;
close ( tmp - > alertpipe [ 1 ] ) ;
goto alertpipe_failed ;
}
}
}
}
} else /* Make sure we've got it done right if they don't */
}
tmp - > alertpipe [ 0 ] = tmp - > alertpipe [ 1 ] = - 1 ;
/*
* This is the last place the channel constructor can fail .
*
* The destructor takes advantage of this fact to ensure that the
* AST_CEL_CHANNEL_END is not posted if we have not posted the
* AST_CEL_CHANNEL_START yet .
*/
if ( ( ast_string_field_init ( tmp , 128 ) ) ) {
return ast_channel_unref ( tmp ) ;
}
/* Always watch the alertpipe */
/* Always watch the alertpipe */
ast_channel_set_fd ( tmp , AST_ALERT_FD , tmp - > alertpipe [ 0 ] ) ;
ast_channel_set_fd ( tmp , AST_ALERT_FD , tmp - > alertpipe [ 0 ] ) ;
/* And timing pipe */
/* And timing pipe */
ast_channel_set_fd ( tmp , AST_TIMING_FD , tmp - > timingfd ) ;
ast_channel_set_fd ( tmp , AST_TIMING_FD , tmp - > timingfd ) ;
ast_string_field_set ( tmp , name , " **Unknown** " ) ;
/* Initial state */
/* Initial state */
tmp - > _state = state ;
tmp - > _state = state ;
@ -964,16 +957,15 @@ alertpipe_failed:
if ( ast_strlen_zero ( ast_config_AST_SYSTEM_NAME ) ) {
if ( ast_strlen_zero ( ast_config_AST_SYSTEM_NAME ) ) {
ast_string_field_build ( tmp , uniqueid , " %li.%d " , ( long ) time ( NULL ) ,
ast_string_field_build ( tmp , uniqueid , " %li.%d " , ( long ) time ( NULL ) ,
ast_atomic_fetchadd_int ( & uniqueint , 1 ) ) ;
ast_atomic_fetchadd_int ( & uniqueint , 1 ) ) ;
} else {
} else {
ast_string_field_build ( tmp , uniqueid , " %s-%li.%d " , ast_config_AST_SYSTEM_NAME ,
ast_string_field_build ( tmp , uniqueid , " %s-%li.%d " , ast_config_AST_SYSTEM_NAME ,
( long ) time ( NULL ) , ast_atomic_fetchadd_int ( & uniqueint , 1 ) ) ;
( long ) time ( NULL ) , ast_atomic_fetchadd_int ( & uniqueint , 1 ) ) ;
}
}
if ( ! ast_strlen_zero ( linkedid ) ) {
if ( ! ast_strlen_zero ( linkedid ) ) {
ast_string_field_set ( tmp , linkedid , linkedid ) ;
ast_string_field_set ( tmp , linkedid , linkedid ) ;
}
} else {
else {
ast_string_field_set ( tmp , linkedid , tmp - > uniqueid ) ;
ast_string_field_set ( tmp , linkedid , tmp - > uniqueid ) ;
}
}
@ -991,6 +983,12 @@ alertpipe_failed:
if ( ( slash = strchr ( tech , ' / ' ) ) ) {
if ( ( slash = strchr ( tech , ' / ' ) ) ) {
* slash = ' \0 ' ;
* slash = ' \0 ' ;
}
}
} else {
/*
* Start the string with ' - ' so it becomes an empty string
* in the destructor .
*/
ast_string_field_set ( tmp , name , " -**Unknown** " ) ;
}
}
/* Reminder for the future: under what conditions do we NOT want to track cdrs on channels? */
/* Reminder for the future: under what conditions do we NOT want to track cdrs on channels? */
@ -1037,8 +1035,8 @@ alertpipe_failed:
ao2_link ( channels , tmp ) ;
ao2_link ( channels , tmp ) ;
/* \!note
/*
* a nd now , since the channel structure is built , and has its name , let ' s
* A nd now , since the channel structure is built , and has its name , let ' s
* call the manager event generator with this Newchannel event . This is the
* call the manager event generator with this Newchannel event . This is the
* proper and correct place to make this call , but you sure do have to pass
* proper and correct place to make this call , but you sure do have to pass
* a lot of data into this func to do it here !
* a lot of data into this func to do it here !
@ -1100,22 +1098,21 @@ struct ast_channel *ast_dummy_channel_alloc(void)
struct varshead * headp ;
struct varshead * headp ;
# if defined(REF_DEBUG)
# if defined(REF_DEBUG)
if ( ! ( tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_dummy_channel_destructor , " dummy channel " , file , line , function , 1 ) ) ) {
tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_dummy_channel_destructor , " dummy channel " ,
return NULL ;
file , line , function , 1 ) ;
}
# elif defined(__AST_DEBUG_MALLOC)
# elif defined(__AST_DEBUG_MALLOC)
if ( ! ( tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_dummy_channel_destructor , " dummy channel " , file , line , function , 0 ) ) ) {
tmp = __ao2_alloc_debug ( sizeof ( * tmp ) , ast_dummy_channel_destructor , " dummy channel " ,
return NULL ;
file , line , function , 0 ) ;
}
# else
# else
if ( ! ( tmp = ao2_alloc ( sizeof ( * tmp ) , ast_dummy_channel_destructor ) ) ) {
tmp = ao2_alloc ( sizeof ( * tmp ) , ast_dummy_channel_destructor ) ;
# endif
if ( ! tmp ) {
/* Dummy channel structure allocation failure. */
return NULL ;
return NULL ;
}
}
# endif
if ( ( ast_string_field_init ( tmp , 128 ) ) ) {
if ( ( ast_string_field_init ( tmp , 128 ) ) ) {
ast_channel_unref ( tmp ) ;
return ast_channel_unref ( tmp ) ;
return NULL ;
}
}
headp = & tmp - > varshead ;
headp = & tmp - > varshead ;
@ -1979,13 +1976,14 @@ static void ast_channel_destructor(void *obj)
struct ast_var_t * vardata ;
struct ast_var_t * vardata ;
struct ast_frame * f ;
struct ast_frame * f ;
struct varshead * headp ;
struct varshead * headp ;
struct ast_datastore * datastore = NULL ;
struct ast_datastore * datastore ;
char name [ AST_CHANNEL_NAME ] , * dashptr ;
char device_name [ AST_CHANNEL_NAME ] ;
headp = & chan - > varshead ;
ast_cel_report_event ( chan , AST_CEL_CHANNEL_END , NULL , NULL , NULL ) ;
if ( chan - > name ) {
ast_cel_check_retire_linkedid ( chan ) ;
/* The string fields were initialized. */
ast_cel_report_event ( chan , AST_CEL_CHANNEL_END , NULL , NULL , NULL ) ;
ast_cel_check_retire_linkedid ( chan ) ;
}
/* Get rid of each of the data stores on the channel */
/* Get rid of each of the data stores on the channel */
ast_channel_lock ( chan ) ;
ast_channel_lock ( chan ) ;
@ -2007,9 +2005,16 @@ static void ast_channel_destructor(void *obj)
if ( chan - > sched )
if ( chan - > sched )
sched_context_destroy ( chan - > sched ) ;
sched_context_destroy ( chan - > sched ) ;
ast_copy_string ( name , chan - > name , sizeof ( name ) ) ;
if ( chan - > name ) {
if ( ( dashptr = strrchr ( name , ' - ' ) ) ) {
char * dashptr ;
* dashptr = ' \0 ' ;
/* The string fields were initialized. */
ast_copy_string ( device_name , chan - > name , sizeof ( device_name ) ) ;
if ( ( dashptr = strrchr ( device_name , ' - ' ) ) ) {
* dashptr = ' \0 ' ;
}
} else {
device_name [ 0 ] = ' \0 ' ;
}
}
/* Stop monitoring */
/* Stop monitoring */
@ -2052,7 +2057,7 @@ static void ast_channel_destructor(void *obj)
/* loop over the variables list, freeing all data and deleting list items */
/* loop over the variables list, freeing all data and deleting list items */
/* no need to lock the list, as the channel is already locked */
/* no need to lock the list, as the channel is already locked */
headp = & chan - > varshead ;
while ( ( vardata = AST_LIST_REMOVE_HEAD ( headp , entries ) ) )
while ( ( vardata = AST_LIST_REMOVE_HEAD ( headp , entries ) ) )
ast_var_delete ( vardata ) ;
ast_var_delete ( vardata ) ;
@ -2072,10 +2077,16 @@ static void ast_channel_destructor(void *obj)
ast_string_field_free_memory ( chan ) ;
ast_string_field_free_memory ( chan ) ;
/* Queue an unknown state, because, while we know that this particular
if ( device_name [ 0 ] ) {
* instance is dead , we don ' t know the state of all other possible
/*
* instances . */
* We have a device name to notify of a new state .
ast_devstate_changed_literal ( AST_DEVICE_UNKNOWN , name ) ;
*
* Queue an unknown state , because , while we know that this particular
* instance is dead , we don ' t know the state of all other possible
* instances .
*/
ast_devstate_changed_literal ( AST_DEVICE_UNKNOWN , device_name ) ;
}
}
}
/*! \brief Free a dummy channel structure */
/*! \brief Free a dummy channel structure */