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 88840442 : static void tevent_common_immediate_cancel(struct tevent_immediate *im)
33 : {
34 88840442 : const char *create_location = im->create_location;
35 88840442 : bool busy = im->busy;
36 88840442 : uint64_t tag = im->tag;
37 88840442 : struct tevent_context *detach_ev_ctx = NULL;
38 :
39 88840442 : if (im->destroyed) {
40 0 : tevent_abort(im->event_ctx, "tevent_immediate use after free");
41 54904564 : return;
42 : }
43 :
44 88840442 : if (im->detach_ev_ctx != NULL) {
45 26102932 : detach_ev_ctx = im->detach_ev_ctx;
46 26102932 : im->detach_ev_ctx = NULL;
47 26102932 : tevent_trace_immediate_callback(detach_ev_ctx,
48 : im,
49 : TEVENT_EVENT_TRACE_DETACH);
50 26102932 : return;
51 : }
52 :
53 62737510 : if (!im->event_ctx) {
54 29002240 : return;
55 : }
56 :
57 33526727 : if (im->handler_name != NULL) {
58 4309231 : 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 33526727 : if (im->cancel_fn) {
65 0 : im->cancel_fn(im);
66 : }
67 :
68 33526727 : if (busy && im->handler_name == NULL) {
69 28980117 : detach_ev_ctx = im->event_ctx;
70 : } else {
71 4546610 : tevent_trace_immediate_callback(im->event_ctx,
72 : im,
73 : TEVENT_EVENT_TRACE_DETACH);
74 : }
75 33526727 : DLIST_REMOVE(im->event_ctx->immediate_events, im);
76 :
77 33526727 : *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 33526727 : if (!busy) {
85 4546607 : talloc_set_destructor(im, NULL);
86 : }
87 : }
88 :
89 : /*
90 : destroy an immediate event
91 : */
92 157312317 : static int tevent_common_immediate_destructor(struct tevent_immediate *im)
93 : {
94 157312317 : if (im->destroyed) {
95 130742086 : tevent_common_check_double_free(im,
96 : "tevent_immediate double free");
97 130742086 : goto done;
98 : }
99 :
100 26570231 : tevent_common_immediate_cancel(im);
101 :
102 26570231 : im->destroyed = true;
103 :
104 157312317 : done:
105 157312317 : if (im->busy) {
106 156231204 : return -1;
107 : }
108 :
109 1075318 : return 0;
110 : }
111 :
112 : /*
113 : * schedule an immediate event on
114 : */
115 33290094 : 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 33290094 : const char *create_location = im->create_location;
123 33290094 : bool busy = im->busy;
124 33290094 : uint64_t tag = im->tag;
125 33290094 : struct tevent_wrapper_glue *glue = im->wrapper;
126 :
127 33290094 : tevent_common_immediate_cancel(im);
128 :
129 33290094 : if (!handler) {
130 24 : return;
131 : }
132 :
133 33290066 : *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 33290066 : tevent_trace_immediate_callback(im->event_ctx, im, TEVENT_EVENT_TRACE_ATTACH);
146 33290066 : DLIST_ADD_END(ev->immediate_events, im);
147 33290066 : talloc_set_destructor(im, tevent_common_immediate_destructor);
148 :
149 33290066 : TEVENT_DEBUG(ev, TEVENT_DEBUG_TRACE,
150 : "Schedule immediate event \"%s\": %p\n",
151 : handler_name, im);
152 : }
153 :
154 28980117 : int tevent_common_invoke_immediate_handler(struct tevent_immediate *im,
155 : bool *removed)
156 : {
157 28980117 : struct tevent_context *handler_ev = im->event_ctx;
158 28980117 : struct tevent_context *ev = im->event_ctx;
159 28980117 : struct tevent_immediate cur = *im;
160 :
161 28980117 : if (removed != NULL) {
162 0 : *removed = false;
163 : }
164 :
165 28980117 : 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 28980117 : im->busy = true;
175 28980117 : im->handler_name = NULL;
176 28980117 : tevent_common_immediate_cancel(im);
177 28980117 : 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 28980117 : tevent_trace_immediate_callback(cur.event_ctx, im, TEVENT_EVENT_TRACE_BEFORE_HANDLER);
190 28980119 : cur.handler(handler_ev, im, cur.private_data);
191 28963918 : 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 28963918 : im->busy = false;
202 :
203 : /* The event was removed in tevent_common_immediate_cancel(). */
204 28963918 : if (im->detach_ev_ctx != NULL) {
205 2877187 : struct tevent_context *detach_ev_ctx = im->detach_ev_ctx;
206 2877187 : im->detach_ev_ctx = NULL;
207 2877187 : tevent_trace_immediate_callback(detach_ev_ctx,
208 : im,
209 : TEVENT_EVENT_TRACE_DETACH);
210 : }
211 :
212 28963918 : if (im->destroyed) {
213 25472917 : talloc_set_destructor(im, NULL);
214 25472917 : TALLOC_FREE(im);
215 25472917 : if (removed != NULL) {
216 0 : *removed = true;
217 : }
218 : }
219 :
220 28963918 : return 0;
221 : }
222 :
223 : /*
224 : trigger the first immediate event and return true
225 : if no event was triggered return false
226 : */
227 28980117 : bool tevent_common_loop_immediate(struct tevent_context *ev)
228 : {
229 28980117 : struct tevent_immediate *im = ev->immediate_events;
230 285015 : int ret;
231 :
232 28980117 : if (!im) {
233 0 : return false;
234 : }
235 :
236 28980117 : ret = tevent_common_invoke_immediate_handler(im, NULL);
237 28963918 : if (ret != 0) {
238 0 : tevent_abort(ev, "tevent_common_invoke_immediate_handler() failed");
239 : }
240 :
241 28678953 : return true;
242 : }
243 :
244 :
245 1138151 : void tevent_immediate_set_tag(struct tevent_immediate *im, uint64_t tag)
246 : {
247 1138151 : if (im == NULL) {
248 0 : return;
249 : }
250 :
251 1138151 : im->tag = tag;
252 : }
253 :
254 883360 : uint64_t tevent_immediate_get_tag(const struct tevent_immediate *im)
255 : {
256 883360 : if (im == NULL) {
257 0 : return 0;
258 : }
259 :
260 883360 : return im->tag;
261 : }
|