LCOV - code coverage report
Current view: top level - lib/tevent - tevent_immediate.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 88 102 86.3 %
Date: 2024-05-31 13:13:24 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    common events code for immediate events
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2009
       7             : 
       8             :      ** NOTE! The following LGPL license applies to the tevent
       9             :      ** library. This does NOT imply that all of Samba is released
      10             :      ** under the LGPL
      11             : 
      12             :    This library is free software; you can redistribute it and/or
      13             :    modify it under the terms of the GNU Lesser General Public
      14             :    License as published by the Free Software Foundation; either
      15             :    version 3 of the License, or (at your option) any later version.
      16             : 
      17             :    This library is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      20             :    Lesser General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU Lesser General Public
      23             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "replace.h"
      27             : #define TEVENT_DEPRECATED 1
      28             : #include "tevent.h"
      29             : #include "tevent_internal.h"
      30             : #include "tevent_util.h"
      31             : 
      32    90489579 : static void tevent_common_immediate_cancel(struct tevent_immediate *im)
      33             : {
      34    90489579 :         const char *create_location = im->create_location;
      35    90489579 :         bool busy = im->busy;
      36    90489579 :         uint64_t tag = im->tag;
      37    90489579 :         struct tevent_context *detach_ev_ctx = NULL;
      38             : 
      39    90489579 :         if (im->destroyed) {
      40           0 :                 tevent_abort(im->event_ctx, "tevent_immediate use after free");
      41    56083595 :                 return;
      42             :         }
      43             : 
      44    90489579 :         if (im->detach_ev_ctx != NULL) {
      45    26715798 :                 detach_ev_ctx = im->detach_ev_ctx;
      46    26715798 :                 im->detach_ev_ctx = NULL;
      47    26715798 :                 tevent_trace_immediate_callback(detach_ev_ctx,
      48             :                                                 im,
      49             :                                                 TEVENT_EVENT_TRACE_DETACH);
      50    26715798 :                 return;
      51             :         }
      52             : 
      53    63773781 :         if (!im->event_ctx) {
      54    29560773 :                 return;
      55             :         }
      56             : 
      57    34012204 :         if (im->handler_name != NULL) {
      58     4265272 :                 TEVENT_DEBUG(im->event_ctx, TEVENT_DEBUG_TRACE,
      59             :                              "Cancel immediate event %p \"%s\"\n",
      60             :                              im, im->handler_name);
      61             :         }
      62             : 
      63             :         /* let the backend free im->additional_data */
      64    34012204 :         if (im->cancel_fn) {
      65           0 :                 im->cancel_fn(im);
      66             :         }
      67             : 
      68    34012204 :         if (busy && im->handler_name == NULL) {
      69    29519017 :                 detach_ev_ctx = im->event_ctx;
      70             :         } else {
      71     4493187 :                 tevent_trace_immediate_callback(im->event_ctx,
      72             :                                                 im,
      73             :                                                 TEVENT_EVENT_TRACE_DETACH);
      74             :         }
      75    34012204 :         DLIST_REMOVE(im->event_ctx->immediate_events, im);
      76             : 
      77    34012204 :         *im = (struct tevent_immediate) {
      78             :                 .create_location        = create_location,
      79             :                 .busy                   = busy,
      80             :                 .tag                    = tag,
      81             :                 .detach_ev_ctx          = detach_ev_ctx,
      82             :         };
      83             : 
      84    34012204 :         if (!busy) {
      85     4493184 :                 talloc_set_destructor(im, NULL);
      86             :         }
      87             : }
      88             : 
      89             : /*
      90             :   destroy an immediate event
      91             : */
      92   158851402 : static int tevent_common_immediate_destructor(struct tevent_immediate *im)
      93             : {
      94   158851402 :         if (im->destroyed) {
      95   131665881 :                 tevent_common_check_double_free(im,
      96             :                                                 "tevent_immediate double free");
      97   131665881 :                 goto done;
      98             :         }
      99             : 
     100    27185521 :         tevent_common_immediate_cancel(im);
     101             : 
     102    27185521 :         im->destroyed = true;
     103             : 
     104   158851402 : done:
     105   158851402 :         if (im->busy) {
     106   157770758 :                 return -1;
     107             :         }
     108             : 
     109     1074809 :         return 0;
     110             : }
     111             : 
     112             : /*
     113             :  * schedule an immediate event on
     114             :  */
     115    33785041 : void tevent_common_schedule_immediate(struct tevent_immediate *im,
     116             :                                       struct tevent_context *ev,
     117             :                                       tevent_immediate_handler_t handler,
     118             :                                       void *private_data,
     119             :                                       const char *handler_name,
     120             :                                       const char *location)
     121             : {
     122    33785041 :         const char *create_location = im->create_location;
     123    33785041 :         bool busy = im->busy;
     124    33785041 :         uint64_t tag = im->tag;
     125    33785041 :         struct tevent_wrapper_glue *glue = im->wrapper;
     126             : 
     127    33785041 :         tevent_common_immediate_cancel(im);
     128             : 
     129    33785041 :         if (!handler) {
     130          26 :                 return;
     131             :         }
     132             : 
     133    33785011 :         *im = (struct tevent_immediate) {
     134             :                 .event_ctx              = ev,
     135             :                 .wrapper                = glue,
     136             :                 .handler                = handler,
     137             :                 .private_data           = private_data,
     138             :                 .handler_name           = handler_name,
     139             :                 .create_location        = create_location,
     140             :                 .schedule_location      = location,
     141             :                 .busy                   = busy,
     142             :                 .tag                    = tag,
     143             :         };
     144             : 
     145    33785011 :         tevent_trace_immediate_callback(im->event_ctx, im, TEVENT_EVENT_TRACE_ATTACH);
     146    33785011 :         DLIST_ADD_END(ev->immediate_events, im);
     147    33785011 :         talloc_set_destructor(im, tevent_common_immediate_destructor);
     148             : 
     149    33785011 :         TEVENT_DEBUG(ev, TEVENT_DEBUG_TRACE,
     150             :                      "Schedule immediate event \"%s\": %p\n",
     151             :                      handler_name, im);
     152             : }
     153             : 
     154    29519017 : int tevent_common_invoke_immediate_handler(struct tevent_immediate *im,
     155             :                                            bool *removed)
     156             : {
     157    29519017 :         struct tevent_context *handler_ev = im->event_ctx;
     158    29519017 :         struct tevent_context *ev = im->event_ctx;
     159    29519017 :         struct tevent_immediate cur = *im;
     160             : 
     161    29519017 :         if (removed != NULL) {
     162           0 :                 *removed = false;
     163             :         }
     164             : 
     165    29519017 :         TEVENT_DEBUG(ev, TEVENT_DEBUG_TRACE,
     166             :                      "Run immediate event \"%s\": %p\n",
     167             :                      im->handler_name, im);
     168             : 
     169             :         /*
     170             :          * remember the handler and then clear the event
     171             :          * the handler might reschedule the event
     172             :          */
     173             : 
     174    29519017 :         im->busy = true;
     175    29519017 :         im->handler_name = NULL;
     176    29519017 :         tevent_common_immediate_cancel(im);
     177    29519017 :         if (cur.wrapper != NULL) {
     178           4 :                 handler_ev = cur.wrapper->wrap_ev;
     179             : 
     180           4 :                 tevent_wrapper_push_use_internal(handler_ev, cur.wrapper);
     181           4 :                 cur.wrapper->ops->before_immediate_handler(
     182           0 :                                         cur.wrapper->wrap_ev,
     183           0 :                                         cur.wrapper->private_state,
     184           0 :                                         cur.wrapper->main_ev,
     185             :                                         im,
     186             :                                         cur.handler_name,
     187             :                                         cur.schedule_location);
     188             :         }
     189    29519017 :         tevent_trace_immediate_callback(cur.event_ctx, im, TEVENT_EVENT_TRACE_BEFORE_HANDLER);
     190    29519017 :         cur.handler(handler_ev, im, cur.private_data);
     191    29502644 :         if (cur.wrapper != NULL) {
     192           4 :                 cur.wrapper->ops->after_immediate_handler(
     193           0 :                                         cur.wrapper->wrap_ev,
     194           0 :                                         cur.wrapper->private_state,
     195           0 :                                         cur.wrapper->main_ev,
     196             :                                         im,
     197             :                                         cur.handler_name,
     198             :                                         cur.schedule_location);
     199           4 :                 tevent_wrapper_pop_use_internal(handler_ev, cur.wrapper);
     200             :         }
     201    29502644 :         im->busy = false;
     202             : 
     203             :         /* The event was removed in tevent_common_immediate_cancel(). */
     204    29502644 :         if (im->detach_ev_ctx != NULL) {
     205     2803219 :                 struct tevent_context *detach_ev_ctx = im->detach_ev_ctx;
     206     2803219 :                 im->detach_ev_ctx = NULL;
     207     2803219 :                 tevent_trace_immediate_callback(detach_ev_ctx,
     208             :                                                 im,
     209             :                                                 TEVENT_EVENT_TRACE_DETACH);
     210             :         }
     211             : 
     212    29502644 :         if (im->destroyed) {
     213    26088504 :                 talloc_set_destructor(im, NULL);
     214    26088504 :                 TALLOC_FREE(im);
     215    26088504 :                 if (removed != NULL) {
     216           0 :                         *removed = true;
     217             :                 }
     218             :         }
     219             : 
     220    29502644 :         return 0;
     221             : }
     222             : 
     223             : /*
     224             :   trigger the first immediate event and return true
     225             :   if no event was triggered return false
     226             : */
     227    29519017 : bool tevent_common_loop_immediate(struct tevent_context *ev)
     228             : {
     229    29519017 :         struct tevent_immediate *im = ev->immediate_events;
     230      268120 :         int ret;
     231             : 
     232    29519017 :         if (!im) {
     233           0 :                 return false;
     234             :         }
     235             : 
     236    29519017 :         ret = tevent_common_invoke_immediate_handler(im, NULL);
     237    29502644 :         if (ret != 0) {
     238           0 :                 tevent_abort(ev, "tevent_common_invoke_immediate_handler() failed");
     239             :         }
     240             : 
     241    29234576 :         return true;
     242             : }
     243             : 
     244             : 
     245      979382 : void tevent_immediate_set_tag(struct tevent_immediate *im, uint64_t tag)
     246             : {
     247      979382 :         if (im == NULL) {
     248           0 :                 return;
     249             :         }
     250             : 
     251      979382 :         im->tag = tag;
     252             : }
     253             : 
     254      770225 : uint64_t tevent_immediate_get_tag(const struct tevent_immediate *im)
     255             : {
     256      770225 :         if (im == NULL) {
     257           0 :                 return 0;
     258             :         }
     259             : 
     260      770225 :         return im->tag;
     261             : }

Generated by: LCOV version 1.14