2005-02-15 13:36:59 +03:00
/*
Unix SMB / CIFS implementation .
main select loop and event handling
Copyright ( C ) Andrew Tridgell 2003
2009-02-16 10:52:06 +03:00
Copyright ( C ) Stefan Metzmacher 2009
* * NOTE ! The following LGPL license applies to the tevent
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
2005-02-15 13:36:59 +03:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2009-02-16 10:52:06 +03:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2005-02-15 13:36:59 +03:00
*/
/*
PLEASE READ THIS BEFORE MODIFYING !
This module is a general abstraction for the main select loop and
event handling . Do not ever put any localised hacks in here , instead
register one of the possible event types and implement that event
somewhere else .
There are 2 types of event handling that are handled in this module :
1 ) a file descriptor becoming readable or writeable . This is mostly
used for network sockets , but can be used for any type of file
descriptor . You may only register one handler for each file
descriptor / io combination or you will get unpredictable results
( this means that you can have a handler for read events , and a
separate handler for write events , but not two handlers that are
both handling read events )
2 ) a timed event . You can register an event that happens at a
specific time . You can register as many of these as you
like . They are single shot - add a new timed event in the event
handler to get another event .
To setup a set of events you first need to create a event_context
2009-01-02 13:30:00 +03:00
structure using the function tevent_context_init ( ) ; This returns a
2008-12-29 22:24:57 +03:00
' struct tevent_context ' that you use in all subsequent calls .
2005-02-15 13:36:59 +03:00
After that you can add / remove events that you are interested in
2009-01-02 13:44:17 +03:00
using tevent_add_ * ( ) and talloc_free ( )
2005-02-15 13:36:59 +03:00
2009-01-02 13:32:29 +03:00
Finally , you call tevent_loop_wait_once ( ) to block waiting for one of the
events to occor or tevent_loop_wait ( ) which will loop
2005-02-15 13:36:59 +03:00
forever .
*/
2008-04-25 01:28:30 +04:00
# include "replace.h"
2009-01-03 14:39:11 +03:00
# include "system/filesys.h"
2009-03-12 11:51:33 +03:00
# define TEVENT_DEPRECATED 1
2008-12-16 21:57:09 +03:00
# include "tevent.h"
# include "tevent_internal.h"
# include "tevent_util.h"
2007-01-05 12:35:49 +03:00
2009-01-02 13:30:00 +03:00
struct tevent_ops_list {
struct tevent_ops_list * next , * prev ;
2007-01-05 12:35:49 +03:00
const char * name ;
2009-01-02 13:30:00 +03:00
const struct tevent_ops * ops ;
2007-01-05 12:35:49 +03:00
} ;
/* list of registered event backends */
2009-01-02 13:30:00 +03:00
static struct tevent_ops_list * tevent_backends = NULL ;
2009-01-02 13:17:00 +03:00
static char * tevent_default_backend = NULL ;
2007-05-14 04:57:48 +04:00
2007-01-05 12:35:49 +03:00
/*
register an events backend
*/
2009-01-02 15:35:32 +03:00
bool tevent_register_backend ( const char * name , const struct tevent_ops * ops )
2007-01-05 12:35:49 +03:00
{
2009-01-02 13:30:00 +03:00
struct tevent_ops_list * e ;
2008-06-14 19:23:31 +04:00
2009-01-02 13:30:00 +03:00
for ( e = tevent_backends ; e ! = NULL ; e = e - > next ) {
2008-06-14 19:23:31 +04:00
if ( 0 = = strcmp ( e - > name , name ) ) {
/* already registered, skip it */
return true ;
}
}
2010-09-24 21:13:05 +04:00
e = talloc ( NULL , struct tevent_ops_list ) ;
2007-10-05 22:03:01 +04:00
if ( e = = NULL ) return false ;
2008-06-14 19:23:31 +04:00
2007-01-05 12:35:49 +03:00
e - > name = name ;
e - > ops = ops ;
2009-01-02 13:30:00 +03:00
DLIST_ADD ( tevent_backends , e ) ;
2008-06-14 19:23:31 +04:00
2007-10-05 22:03:01 +04:00
return true ;
2007-01-05 12:35:49 +03:00
}
2007-05-14 04:57:48 +04:00
/*
set the default event backend
*/
2009-01-02 13:17:00 +03:00
void tevent_set_default_backend ( const char * backend )
2007-05-14 04:57:48 +04:00
{
2009-01-02 13:17:00 +03:00
talloc_free ( tevent_default_backend ) ;
2010-09-24 21:13:05 +04:00
tevent_default_backend = talloc_strdup ( NULL , backend ) ;
2007-05-14 04:57:48 +04:00
}
2007-01-05 12:35:49 +03:00
/*
initialise backends if not already done
*/
2009-01-02 13:30:00 +03:00
static void tevent_backend_init ( void )
2007-01-05 12:35:49 +03:00
{
2009-01-02 15:35:32 +03:00
tevent_select_init ( ) ;
2011-02-09 17:28:10 +03:00
tevent_poll_init ( ) ;
2012-08-13 18:06:01 +04:00
tevent_poll_mt_init ( ) ;
2009-01-02 15:39:26 +03:00
# ifdef HAVE_EPOLL
2009-01-02 15:35:32 +03:00
tevent_epoll_init ( ) ;
2007-05-14 04:57:48 +04:00
# endif
2013-02-11 22:36:52 +04:00
tevent_standard_init ( ) ;
2007-01-05 12:35:49 +03:00
}
2013-02-11 22:56:58 +04:00
_PRIVATE_ const struct tevent_ops * tevent_find_ops_byname ( const char * name )
{
struct tevent_ops_list * e ;
tevent_backend_init ( ) ;
if ( name = = NULL ) {
name = tevent_default_backend ;
}
if ( name = = NULL ) {
name = " standard " ;
}
for ( e = tevent_backends ; e ! = NULL ; e = e - > next ) {
if ( 0 = = strcmp ( e - > name , name ) ) {
return e - > ops ;
}
}
return NULL ;
}
2007-01-05 12:35:49 +03:00
/*
list available backends
*/
2009-01-02 13:30:00 +03:00
const char * * tevent_backend_list ( TALLOC_CTX * mem_ctx )
2007-01-05 12:35:49 +03:00
{
const char * * list = NULL ;
2009-01-02 13:30:00 +03:00
struct tevent_ops_list * e ;
2007-01-05 12:35:49 +03:00
2009-01-02 13:30:00 +03:00
tevent_backend_init ( ) ;
2007-01-05 12:35:49 +03:00
2009-01-02 13:30:00 +03:00
for ( e = tevent_backends ; e ; e = e - > next ) {
2008-06-14 19:23:31 +04:00
list = ev_str_list_add ( list , e - > name ) ;
2007-01-05 12:35:49 +03:00
}
talloc_steal ( mem_ctx , list ) ;
return list ;
}
2005-02-15 13:36:59 +03:00
2009-01-05 21:23:23 +03:00
int tevent_common_context_destructor ( struct tevent_context * ev )
{
2009-01-12 11:20:57 +03:00
struct tevent_fd * fd , * fn ;
struct tevent_timer * te , * tn ;
2009-03-13 17:47:33 +03:00
struct tevent_immediate * ie , * in ;
2009-01-12 11:20:57 +03:00
struct tevent_signal * se , * sn ;
2009-01-05 21:23:23 +03:00
if ( ev - > pipe_fde ) {
talloc_free ( ev - > pipe_fde ) ;
2009-08-28 06:41:23 +04:00
close ( ev - > pipe_fds [ 0 ] ) ;
close ( ev - > pipe_fds [ 1 ] ) ;
2009-01-05 21:23:23 +03:00
ev - > pipe_fde = NULL ;
}
2009-01-12 11:20:57 +03:00
for ( fd = ev - > fd_events ; fd ; fd = fn ) {
fn = fd - > next ;
2009-01-05 21:23:23 +03:00
fd - > event_ctx = NULL ;
DLIST_REMOVE ( ev - > fd_events , fd ) ;
}
2009-01-12 11:20:57 +03:00
for ( te = ev - > timer_events ; te ; te = tn ) {
tn = te - > next ;
2009-01-05 21:23:23 +03:00
te - > event_ctx = NULL ;
2009-01-11 22:00:50 +03:00
DLIST_REMOVE ( ev - > timer_events , te ) ;
2009-01-05 21:23:23 +03:00
}
2009-03-13 17:47:33 +03:00
for ( ie = ev - > immediate_events ; ie ; ie = in ) {
in = ie - > next ;
ie - > event_ctx = NULL ;
ie - > cancel_fn = NULL ;
DLIST_REMOVE ( ev - > immediate_events , ie ) ;
}
2009-01-12 11:20:57 +03:00
for ( se = ev - > signal_events ; se ; se = sn ) {
sn = se - > next ;
2009-01-05 21:23:23 +03:00
se - > event_ctx = NULL ;
DLIST_REMOVE ( ev - > signal_events , se ) ;
2010-02-09 12:02:20 +03:00
/*
* This is important , Otherwise signals
* are handled twice in child . eg , SIGHUP .
* one added in parent , and another one in
* the child . - - BoYang
*/
tevent_cleanup_pending_signal_handlers ( se ) ;
2009-01-05 21:23:23 +03:00
}
2011-08-12 05:56:28 +04:00
/* removing nesting hook or we get an abort when nesting is
* not allowed . - - SSS
* Note that we need to leave the allowed flag at its current
* value , otherwise the use in tevent_re_initialise ( ) will
* leave the event context with allowed forced to false , which
* will break users that expect nesting to be allowed
*/
2011-04-26 07:40:15 +04:00
ev - > nesting . level = 0 ;
ev - > nesting . hook_fn = NULL ;
ev - > nesting . hook_private = NULL ;
2009-01-05 21:23:23 +03:00
return 0 ;
}
2005-02-15 13:36:59 +03:00
/*
create a event_context structure for a specific implemementation .
This must be the first events call , and all subsequent calls pass
this event_context as the first element . Event handlers also
receive this as their first argument .
This function is for allowing third - party - applications to hook in gluecode
to their own event loop code , so that they can make async usage of our client libs
2009-01-02 13:30:00 +03:00
NOTE : use tevent_context_init ( ) inside of samba !
2005-02-15 13:36:59 +03:00
*/
2012-05-11 17:19:55 +04:00
struct tevent_context * tevent_context_init_ops ( TALLOC_CTX * mem_ctx ,
const struct tevent_ops * ops ,
void * additional_data )
2005-02-15 13:36:59 +03:00
{
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ;
2005-02-15 13:36:59 +03:00
int ret ;
2008-12-29 22:24:57 +03:00
ev = talloc_zero ( mem_ctx , struct tevent_context ) ;
2005-02-15 13:36:59 +03:00
if ( ! ev ) return NULL ;
2009-01-05 21:23:23 +03:00
talloc_set_destructor ( ev , tevent_common_context_destructor ) ;
2005-02-15 13:36:59 +03:00
ev - > ops = ops ;
2012-05-11 17:19:55 +04:00
ev - > additional_data = additional_data ;
2005-02-15 13:36:59 +03:00
2007-01-05 12:35:49 +03:00
ret = ev - > ops - > context_init ( ev ) ;
2005-02-15 13:36:59 +03:00
if ( ret ! = 0 ) {
talloc_free ( ev ) ;
return NULL ;
}
return ev ;
}
2007-01-05 12:35:49 +03:00
/*
create a event_context structure . This must be the first events
call , and all subsequent calls pass this event_context as the first
element . Event handlers also receive this as their first argument .
*/
2009-01-02 13:30:00 +03:00
struct tevent_context * tevent_context_init_byname ( TALLOC_CTX * mem_ctx ,
const char * name )
2007-01-05 12:35:49 +03:00
{
2009-01-02 13:30:00 +03:00
struct tevent_ops_list * e ;
2007-01-05 12:35:49 +03:00
2009-01-02 13:30:00 +03:00
tevent_backend_init ( ) ;
2007-01-05 12:35:49 +03:00
2007-05-14 04:57:48 +04:00
if ( name = = NULL ) {
2009-01-02 13:17:00 +03:00
name = tevent_default_backend ;
2007-05-14 04:57:48 +04:00
}
2007-01-09 03:00:30 +03:00
if ( name = = NULL ) {
name = " standard " ;
}
2009-01-02 13:30:00 +03:00
for ( e = tevent_backends ; e ; e = e - > next ) {
2007-01-05 12:35:49 +03:00
if ( strcmp ( name , e - > name ) = = 0 ) {
2012-05-11 17:19:55 +04:00
return tevent_context_init_ops ( mem_ctx , e - > ops , NULL ) ;
2007-01-05 12:35:49 +03:00
}
}
return NULL ;
}
2005-02-15 13:36:59 +03:00
/*
create a event_context structure . This must be the first events
call , and all subsequent calls pass this event_context as the first
element . Event handlers also receive this as their first argument .
*/
2009-01-02 13:30:00 +03:00
struct tevent_context * tevent_context_init ( TALLOC_CTX * mem_ctx )
2005-02-15 13:36:59 +03:00
{
2009-01-02 13:30:00 +03:00
return tevent_context_init_byname ( mem_ctx , NULL ) ;
2005-02-15 13:36:59 +03:00
}
/*
add a fd based event
return NULL on failure ( memory allocation error )
*/
2009-01-02 13:44:17 +03:00
struct tevent_fd * _tevent_add_fd ( struct tevent_context * ev ,
TALLOC_CTX * mem_ctx ,
int fd ,
uint16_t flags ,
tevent_fd_handler_t handler ,
void * private_data ,
const char * handler_name ,
const char * location )
2005-02-15 13:36:59 +03:00
{
2009-01-02 15:26:32 +03:00
return ev - > ops - > add_fd ( ev , mem_ctx , fd , flags , handler , private_data ,
handler_name , location ) ;
2005-02-15 13:36:59 +03:00
}
2009-01-03 13:27:00 +03:00
/*
set a close function on the fd event
*/
void tevent_fd_set_close_fn ( struct tevent_fd * fde ,
tevent_fd_close_fn_t close_fn )
{
if ( ! fde ) return ;
2009-01-07 08:30:37 +03:00
if ( ! fde - > event_ctx ) return ;
2009-01-03 13:27:00 +03:00
fde - > event_ctx - > ops - > set_fd_close_fn ( fde , close_fn ) ;
}
2009-01-03 14:39:11 +03:00
static void tevent_fd_auto_close_fn ( struct tevent_context * ev ,
struct tevent_fd * fde ,
int fd ,
void * private_data )
{
close ( fd ) ;
}
void tevent_fd_set_auto_close ( struct tevent_fd * fde )
{
tevent_fd_set_close_fn ( fde , tevent_fd_auto_close_fn ) ;
}
2005-02-15 13:36:59 +03:00
/*
return the fd event flags
*/
2009-01-02 13:36:52 +03:00
uint16_t tevent_fd_get_flags ( struct tevent_fd * fde )
2005-02-15 13:36:59 +03:00
{
2005-12-08 11:31:59 +03:00
if ( ! fde ) return 0 ;
2009-01-07 08:30:37 +03:00
if ( ! fde - > event_ctx ) return 0 ;
2005-02-15 13:36:59 +03:00
return fde - > event_ctx - > ops - > get_fd_flags ( fde ) ;
}
/*
set the fd event flags
*/
2009-01-02 13:36:52 +03:00
void tevent_fd_set_flags ( struct tevent_fd * fde , uint16_t flags )
2005-02-15 13:36:59 +03:00
{
2005-12-08 11:31:59 +03:00
if ( ! fde ) return ;
2009-01-07 08:30:37 +03:00
if ( ! fde - > event_ctx ) return ;
2005-02-15 13:36:59 +03:00
fde - > event_ctx - > ops - > set_fd_flags ( fde , flags ) ;
}
2009-03-12 10:48:59 +03:00
bool tevent_signal_support ( struct tevent_context * ev )
{
if ( ev - > ops - > add_signal ) {
return true ;
}
return false ;
}
2009-03-12 11:22:41 +03:00
static void ( * tevent_abort_fn ) ( const char * reason ) ;
void tevent_set_abort_fn ( void ( * abort_fn ) ( const char * reason ) )
{
tevent_abort_fn = abort_fn ;
}
static void tevent_abort ( struct tevent_context * ev , const char * reason )
{
tevent_debug ( ev , TEVENT_DEBUG_FATAL ,
" abort: %s \n " , reason ) ;
if ( ! tevent_abort_fn ) {
abort ( ) ;
}
tevent_abort_fn ( reason ) ;
}
2005-02-15 13:36:59 +03:00
/*
2009-01-02 13:44:17 +03:00
add a timer event
2005-02-15 13:36:59 +03:00
return NULL on failure
*/
2009-01-02 13:44:17 +03:00
struct tevent_timer * _tevent_add_timer ( struct tevent_context * ev ,
TALLOC_CTX * mem_ctx ,
struct timeval next_event ,
tevent_timer_handler_t handler ,
void * private_data ,
const char * handler_name ,
const char * location )
2005-02-15 13:36:59 +03:00
{
2009-01-02 15:26:32 +03:00
return ev - > ops - > add_timer ( ev , mem_ctx , next_event , handler , private_data ,
handler_name , location ) ;
2005-02-15 13:36:59 +03:00
}
2009-03-13 17:47:33 +03:00
/*
allocate an immediate event
return NULL on failure ( memory allocation error )
*/
struct tevent_immediate * _tevent_create_immediate ( TALLOC_CTX * mem_ctx ,
const char * location )
{
struct tevent_immediate * im ;
im = talloc ( mem_ctx , struct tevent_immediate ) ;
if ( im = = NULL ) return NULL ;
im - > prev = NULL ;
im - > next = NULL ;
im - > event_ctx = NULL ;
im - > create_location = location ;
im - > handler = NULL ;
im - > private_data = NULL ;
im - > handler_name = NULL ;
im - > schedule_location = NULL ;
im - > cancel_fn = NULL ;
im - > additional_data = NULL ;
return im ;
}
/*
schedule an immediate event
*/
void _tevent_schedule_immediate ( struct tevent_immediate * im ,
struct tevent_context * ev ,
tevent_immediate_handler_t handler ,
void * private_data ,
const char * handler_name ,
const char * location )
{
ev - > ops - > schedule_immediate ( im , ev , handler , private_data ,
handler_name , location ) ;
}
2007-01-21 11:23:14 +03:00
/*
add a signal event
2007-01-21 13:32:39 +03:00
sa_flags are flags to sigaction ( 2 )
2007-01-21 11:23:14 +03:00
return NULL on failure
*/
2009-01-02 13:44:17 +03:00
struct tevent_signal * _tevent_add_signal ( struct tevent_context * ev ,
TALLOC_CTX * mem_ctx ,
int signum ,
int sa_flags ,
tevent_signal_handler_t handler ,
void * private_data ,
const char * handler_name ,
const char * location )
2007-01-21 11:23:14 +03:00
{
2009-01-02 15:26:32 +03:00
return ev - > ops - > add_signal ( ev , mem_ctx , signum , sa_flags , handler , private_data ,
handler_name , location ) ;
2007-01-21 11:23:14 +03:00
}
2009-03-12 11:51:33 +03:00
void tevent_loop_allow_nesting ( struct tevent_context * ev )
{
ev - > nesting . allowed = true ;
}
2009-03-12 12:23:30 +03:00
void tevent_loop_set_nesting_hook ( struct tevent_context * ev ,
tevent_nesting_hook hook ,
void * private_data )
{
2009-03-19 03:21:36 +03:00
if ( ev - > nesting . hook_fn & &
( ev - > nesting . hook_fn ! = hook | |
ev - > nesting . hook_private ! = private_data ) ) {
/* the way the nesting hook code is currently written
we cannot support two different nesting hooks at the
same time . */
tevent_abort ( ev , " tevent: Violation of nesting hook rules \n " ) ;
}
2009-03-12 12:23:30 +03:00
ev - > nesting . hook_fn = hook ;
ev - > nesting . hook_private = private_data ;
}
2009-03-12 11:51:33 +03:00
static void tevent_abort_nesting ( struct tevent_context * ev , const char * location )
{
const char * reason ;
reason = talloc_asprintf ( NULL , " tevent_loop_once() nesting at %s " ,
location ) ;
if ( ! reason ) {
reason = " tevent_loop_once() nesting " ;
}
tevent_abort ( ev , reason ) ;
}
2005-02-15 13:36:59 +03:00
/*
do a single event loop using the events defined in ev
*/
2009-03-12 11:33:26 +03:00
int _tevent_loop_once ( struct tevent_context * ev , const char * location )
2005-02-15 13:36:59 +03:00
{
2009-03-12 11:51:33 +03:00
int ret ;
2009-03-12 12:23:30 +03:00
void * nesting_stack_ptr = NULL ;
2009-03-12 11:51:33 +03:00
ev - > nesting . level + + ;
if ( ev - > nesting . level > 1 ) {
if ( ! ev - > nesting . allowed ) {
tevent_abort_nesting ( ev , location ) ;
errno = ELOOP ;
return - 1 ;
}
2009-03-19 16:31:43 +03:00
}
if ( ev - > nesting . level > 0 ) {
2009-03-12 12:23:30 +03:00
if ( ev - > nesting . hook_fn ) {
int ret2 ;
ret2 = ev - > nesting . hook_fn ( ev ,
ev - > nesting . hook_private ,
ev - > nesting . level ,
true ,
( void * ) & nesting_stack_ptr ,
location ) ;
if ( ret2 ! = 0 ) {
ret = ret2 ;
goto done ;
}
}
2009-03-12 11:51:33 +03:00
}
ret = ev - > ops - > loop_once ( ev , location ) ;
2009-03-19 16:31:43 +03:00
if ( ev - > nesting . level > 0 ) {
2009-03-12 12:23:30 +03:00
if ( ev - > nesting . hook_fn ) {
int ret2 ;
ret2 = ev - > nesting . hook_fn ( ev ,
ev - > nesting . hook_private ,
ev - > nesting . level ,
false ,
( void * ) & nesting_stack_ptr ,
location ) ;
if ( ret2 ! = 0 ) {
ret = ret2 ;
goto done ;
}
}
}
2009-03-12 11:51:33 +03:00
2009-03-12 12:23:30 +03:00
done :
ev - > nesting . level - - ;
2009-03-12 11:51:33 +03:00
return ret ;
2005-02-15 13:36:59 +03:00
}
2009-03-12 12:35:23 +03:00
/*
this is a performance optimization for the samba4 nested event loop problems
*/
int _tevent_loop_until ( struct tevent_context * ev ,
bool ( * finished ) ( void * private_data ) ,
void * private_data ,
const char * location )
{
2009-03-12 20:44:36 +03:00
int ret = 0 ;
2009-03-12 12:35:23 +03:00
void * nesting_stack_ptr = NULL ;
ev - > nesting . level + + ;
if ( ev - > nesting . level > 1 ) {
if ( ! ev - > nesting . allowed ) {
tevent_abort_nesting ( ev , location ) ;
errno = ELOOP ;
return - 1 ;
}
2009-03-19 16:31:43 +03:00
}
if ( ev - > nesting . level > 0 ) {
2009-03-12 12:35:23 +03:00
if ( ev - > nesting . hook_fn ) {
int ret2 ;
ret2 = ev - > nesting . hook_fn ( ev ,
ev - > nesting . hook_private ,
ev - > nesting . level ,
true ,
( void * ) & nesting_stack_ptr ,
location ) ;
if ( ret2 ! = 0 ) {
ret = ret2 ;
goto done ;
}
}
}
while ( ! finished ( private_data ) ) {
ret = ev - > ops - > loop_once ( ev , location ) ;
if ( ret ! = 0 ) {
break ;
}
}
2009-03-19 16:31:43 +03:00
if ( ev - > nesting . level > 0 ) {
2009-03-12 12:35:23 +03:00
if ( ev - > nesting . hook_fn ) {
int ret2 ;
ret2 = ev - > nesting . hook_fn ( ev ,
ev - > nesting . hook_private ,
ev - > nesting . level ,
false ,
( void * ) & nesting_stack_ptr ,
location ) ;
if ( ret2 ! = 0 ) {
ret = ret2 ;
goto done ;
}
}
}
done :
ev - > nesting . level - - ;
return ret ;
}
2009-03-16 16:15:07 +03:00
/*
return on failure or ( with 0 ) if all fd events are removed
*/
int tevent_common_loop_wait ( struct tevent_context * ev ,
const char * location )
{
/*
* loop as long as we have events pending
*/
while ( ev - > fd_events | |
ev - > timer_events | |
ev - > immediate_events | |
ev - > signal_events ) {
int ret ;
ret = _tevent_loop_once ( ev , location ) ;
if ( ret ! = 0 ) {
tevent_debug ( ev , TEVENT_DEBUG_FATAL ,
" _tevent_loop_once() failed: %d - %s \n " ,
ret , strerror ( errno ) ) ;
return ret ;
}
}
tevent_debug ( ev , TEVENT_DEBUG_WARNING ,
" tevent_common_loop_wait() out of events \n " ) ;
return 0 ;
}
2005-02-15 13:36:59 +03:00
/*
return on failure or ( with 0 ) if all fd events are removed
*/
2009-03-12 11:33:26 +03:00
int _tevent_loop_wait ( struct tevent_context * ev , const char * location )
2005-02-15 13:36:59 +03:00
{
2009-03-19 16:31:43 +03:00
return ev - > ops - > loop_wait ( ev , location ) ;
2005-02-15 13:36:59 +03:00
}
2010-03-26 13:13:27 +03:00
/*
re - initialise a tevent context . This leaves you with the same
event context , but all events are wiped and the structure is
re - initialised . This is most useful after a fork ( )
zero is returned on success , non - zero on failure
*/
int tevent_re_initialise ( struct tevent_context * ev )
{
tevent_common_context_destructor ( ev ) ;
return ev - > ops - > context_init ( ev ) ;
}