2009-03-13 17:47:33 +03:00
/*
Unix SMB / CIFS implementation .
common events code for immediate events
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 ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
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/>.
*/
# include "replace.h"
2019-01-08 17:25:22 +03:00
# define TEVENT_DEPRECATED 1
2009-03-13 17:47:33 +03:00
# include "tevent.h"
# include "tevent_internal.h"
# include "tevent_util.h"
static void tevent_common_immediate_cancel ( struct tevent_immediate * im )
{
2014-10-23 09:15:14 +04:00
const char * create_location = im - > create_location ;
2014-07-22 15:08:42 +04:00
bool busy = im - > busy ;
2021-06-01 15:10:05 +03:00
uint64_t tag = im - > tag ;
struct tevent_context * detach_ev_ctx = NULL ;
2014-07-22 15:08:42 +04:00
if ( im - > destroyed ) {
tevent_abort ( im - > event_ctx , " tevent_immediate use after free " ) ;
return ;
}
2014-10-23 09:15:14 +04:00
2021-06-01 15:10:05 +03:00
if ( im - > detach_ev_ctx ! = NULL ) {
detach_ev_ctx = im - > detach_ev_ctx ;
im - > detach_ev_ctx = NULL ;
tevent_trace_immediate_callback ( detach_ev_ctx ,
im ,
TEVENT_EVENT_TRACE_DETACH ) ;
return ;
}
2009-03-13 17:47:33 +03:00
if ( ! im - > event_ctx ) {
return ;
}
2018-03-23 12:25:27 +03:00
if ( im - > handler_name ! = NULL ) {
tevent_debug ( im - > event_ctx , TEVENT_DEBUG_TRACE ,
" Cancel immediate event %p \" %s \" \n " ,
im , im - > handler_name ) ;
}
2009-03-13 17:47:33 +03:00
/* let the backend free im->additional_data */
if ( im - > cancel_fn ) {
im - > cancel_fn ( im ) ;
}
2021-06-01 15:10:05 +03:00
if ( busy & & im - > handler_name = = NULL ) {
detach_ev_ctx = im - > event_ctx ;
} else {
tevent_trace_immediate_callback ( im - > event_ctx ,
im ,
TEVENT_EVENT_TRACE_DETACH ) ;
}
2009-03-13 17:47:33 +03:00
DLIST_REMOVE ( im - > event_ctx - > immediate_events , im ) ;
2014-10-23 09:15:14 +04:00
* im = ( struct tevent_immediate ) {
. create_location = create_location ,
2014-07-22 15:08:42 +04:00
. busy = busy ,
2021-06-01 15:10:05 +03:00
. tag = tag ,
. detach_ev_ctx = detach_ev_ctx ,
2014-10-23 09:15:14 +04:00
} ;
2009-03-13 17:47:33 +03:00
2014-07-22 15:08:42 +04:00
if ( ! busy ) {
talloc_set_destructor ( im , NULL ) ;
}
2009-03-13 17:47:33 +03:00
}
/*
destroy an immediate event
*/
static int tevent_common_immediate_destructor ( struct tevent_immediate * im )
{
2014-07-22 15:08:42 +04:00
if ( im - > destroyed ) {
tevent_common_check_double_free ( im ,
" tevent_immediate double free " ) ;
goto done ;
}
2009-03-13 17:47:33 +03:00
tevent_common_immediate_cancel ( im ) ;
2014-07-22 15:08:42 +04:00
im - > destroyed = true ;
done :
if ( im - > busy ) {
return - 1 ;
}
2009-03-13 17:47:33 +03:00
return 0 ;
}
/*
* schedule an immediate event on
*/
void tevent_common_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 )
{
2014-10-23 09:15:14 +04:00
const char * create_location = im - > create_location ;
2014-07-22 15:08:42 +04:00
bool busy = im - > busy ;
2021-06-01 14:57:45 +03:00
uint64_t tag = im - > tag ;
2014-07-22 18:51:38 +04:00
struct tevent_wrapper_glue * glue = im - > wrapper ;
2014-10-23 09:15:14 +04:00
2009-03-13 17:47:33 +03:00
tevent_common_immediate_cancel ( im ) ;
if ( ! handler ) {
return ;
}
2014-10-23 09:15:14 +04:00
* im = ( struct tevent_immediate ) {
. event_ctx = ev ,
2014-07-22 18:51:38 +04:00
. wrapper = glue ,
2014-10-23 09:15:14 +04:00
. handler = handler ,
. private_data = private_data ,
. handler_name = handler_name ,
. create_location = create_location ,
. schedule_location = location ,
2014-07-22 15:08:42 +04:00
. busy = busy ,
2021-06-01 14:57:45 +03:00
. tag = tag ,
2014-10-23 09:15:14 +04:00
} ;
2009-03-13 17:47:33 +03:00
2021-06-01 15:10:05 +03:00
tevent_trace_immediate_callback ( im - > event_ctx , im , TEVENT_EVENT_TRACE_ATTACH ) ;
2016-02-05 13:37:42 +03:00
DLIST_ADD_END ( ev - > immediate_events , im ) ;
2009-03-13 17:47:33 +03:00
talloc_set_destructor ( im , tevent_common_immediate_destructor ) ;
tevent_debug ( ev , TEVENT_DEBUG_TRACE ,
" Schedule immediate event \" %s \" : %p \n " ,
handler_name , im ) ;
}
2014-07-22 15:08:42 +04:00
int tevent_common_invoke_immediate_handler ( struct tevent_immediate * im ,
bool * removed )
2009-03-13 17:47:33 +03:00
{
2014-07-22 18:51:38 +04:00
struct tevent_context * handler_ev = im - > event_ctx ;
2014-07-22 15:08:42 +04:00
struct tevent_context * ev = im - > event_ctx ;
struct tevent_immediate cur = * im ;
2009-03-13 17:47:33 +03:00
2014-07-22 15:08:42 +04:00
if ( removed ! = NULL ) {
* removed = false ;
2009-03-13 17:47:33 +03:00
}
tevent_debug ( ev , TEVENT_DEBUG_TRACE ,
" Run immediate event \" %s \" : %p \n " ,
im - > handler_name , im ) ;
/*
* remember the handler and then clear the event
* the handler might reschedule the event
*/
2014-07-22 15:08:42 +04:00
im - > busy = true ;
im - > handler_name = NULL ;
tevent_common_immediate_cancel ( im ) ;
2014-07-22 18:51:38 +04:00
if ( cur . wrapper ! = NULL ) {
handler_ev = cur . wrapper - > wrap_ev ;
tevent_wrapper_push_use_internal ( handler_ev , cur . wrapper ) ;
cur . wrapper - > ops - > before_immediate_handler (
cur . wrapper - > wrap_ev ,
cur . wrapper - > private_state ,
cur . wrapper - > main_ev ,
im ,
cur . handler_name ,
cur . schedule_location ) ;
}
2021-06-01 15:10:05 +03:00
tevent_trace_immediate_callback ( cur . event_ctx , im , TEVENT_EVENT_TRACE_BEFORE_HANDLER ) ;
2014-07-22 18:51:38 +04:00
cur . handler ( handler_ev , im , cur . private_data ) ;
if ( cur . wrapper ! = NULL ) {
cur . wrapper - > ops - > after_immediate_handler (
cur . wrapper - > wrap_ev ,
cur . wrapper - > private_state ,
cur . wrapper - > main_ev ,
im ,
cur . handler_name ,
cur . schedule_location ) ;
tevent_wrapper_pop_use_internal ( handler_ev , cur . wrapper ) ;
}
2014-07-22 15:08:42 +04:00
im - > busy = false ;
2021-06-01 15:10:05 +03:00
/* The event was removed in tevent_common_immediate_cancel(). */
if ( im - > detach_ev_ctx ! = NULL ) {
struct tevent_context * detach_ev_ctx = im - > detach_ev_ctx ;
im - > detach_ev_ctx = NULL ;
tevent_trace_immediate_callback ( detach_ev_ctx ,
im ,
TEVENT_EVENT_TRACE_DETACH ) ;
}
2014-07-22 15:08:42 +04:00
if ( im - > destroyed ) {
talloc_set_destructor ( im , NULL ) ;
TALLOC_FREE ( im ) ;
if ( removed ! = NULL ) {
* removed = true ;
}
}
return 0 ;
}
/*
trigger the first immediate event and return true
if no event was triggered return false
*/
bool tevent_common_loop_immediate ( struct tevent_context * ev )
{
struct tevent_immediate * im = ev - > immediate_events ;
int ret ;
2009-03-13 17:47:33 +03:00
2014-07-22 15:08:42 +04:00
if ( ! im ) {
return false ;
}
2009-03-13 17:47:33 +03:00
2014-07-22 15:08:42 +04:00
ret = tevent_common_invoke_immediate_handler ( im , NULL ) ;
if ( ret ! = 0 ) {
tevent_abort ( ev , " tevent_common_invoke_immediate_handler() failed " ) ;
}
2009-03-13 17:47:33 +03:00
return true ;
}
2021-06-01 14:57:45 +03:00
void tevent_immediate_set_tag ( struct tevent_immediate * im , uint64_t tag )
{
if ( im = = NULL ) {
return ;
}
im - > tag = tag ;
}
uint64_t tevent_immediate_get_tag ( const struct tevent_immediate * im )
{
if ( im = = NULL ) {
return 0 ;
}
return im - > tag ;
}