tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_have_events: bool (struct tevent_context *)
+tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *)
tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *)
tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *)
tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *)
*/
flags &= fde->flags;
if (flags) {
- fde->handler(epoll_ev->ev, fde, flags, fde->private_data);
- break;
+ return tevent_common_invoke_fd_handler(fde, flags, NULL);
}
}
int tevent_common_fd_destructor(struct tevent_fd *fde)
{
+ if (fde->destroyed) {
+ tevent_common_check_double_free(fde, "tevent_fd double free");
+ goto done;
+ }
+ fde->destroyed = true;
+
if (fde->event_ctx) {
DLIST_REMOVE(fde->event_ctx->fd_events, fde);
}
if (fde->close_fn) {
fde->close_fn(fde->event_ctx, fde, fde->fd, fde->private_data);
fde->fd = -1;
+ fde->close_fn = NULL;
+ }
+
+ fde->event_ctx = NULL;
+done:
+ if (fde->busy) {
+ return -1;
}
return 0;
{
fde->close_fn = close_fn;
}
+
+int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags,
+ bool *removed)
+{
+ if (removed != NULL) {
+ *removed = false;
+ }
+
+ if (fde->event_ctx == NULL) {
+ return 0;
+ }
+
+ fde->busy = true;
+ fde->handler(fde->event_ctx, fde, flags, fde->private_data);
+ fde->busy = false;
+
+ if (fde->destroyed) {
+ talloc_set_destructor(fde, NULL);
+ TALLOC_FREE(fde);
+ if (removed != NULL) {
+ *removed = true;
+ }
+ }
+
+ return 0;
+}
struct tevent_fd {
struct tevent_fd *prev, *next;
struct tevent_context *event_ctx;
+ bool busy;
+ bool destroyed;
int fd;
uint16_t flags; /* see TEVENT_FD_* flags */
tevent_fd_handler_t handler;
tevent_fd_close_fn_t close_fn);
uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde);
void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags);
+int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags,
+ bool *removed);
struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
flags &= fde->flags;
if (flags != 0) {
DLIST_DEMOTE(ev->fd_events, fde);
- fde->handler(ev, fde, flags, fde->private_data);
- return 0;
+ return tevent_common_invoke_fd_handler(fde, flags, NULL);
}
}
*/
flags &= fde->flags;
if (flags) {
- fde->handler(ev, fde, flags, fde->private_data);
- break;
+ return tevent_common_invoke_fd_handler(fde, flags, NULL);
}
}