select e_fds
[metze/samba/wip.git] / lib / tevent / tevent_select.c
index 24032631f8ab126b3aa8abd854a93d61805c0853..9dfe703793233de4d5bdcabc80bfae782176800c 100644 (file)
@@ -35,9 +35,6 @@ struct select_event_context {
 
        /* the maximum file descriptor number in fd_events */
        int maxfd;
-
-       /* information for exiting from the event loop */
-       int exit_code;
 };
 
 /*
@@ -91,8 +88,8 @@ static int select_event_fd_destructor(struct tevent_fd *fde)
        struct select_event_context *select_ev = NULL;
 
        if (ev) {
-               select_ev = talloc_get_type(ev->additional_data,
-                                           struct select_event_context);
+               select_ev = talloc_get_type_abort(ev->additional_data,
+                                                 struct select_event_context);
 
                if (select_ev->maxfd == fde->fd) {
                        select_ev->maxfd = EVENT_INVALID_MAXFD;
@@ -113,8 +110,9 @@ static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_C
                                             const char *handler_name,
                                             const char *location)
 {
-       struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
-                                                          struct select_event_context);
+       struct select_event_context *select_ev =
+               talloc_get_type_abort(ev->additional_data,
+               struct select_event_context);
        struct tevent_fd *fde;
 
        if (fd < 0 || fd >= FD_SETSIZE) {
@@ -141,7 +139,7 @@ static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_C
 */
 static int select_event_loop_select(struct select_event_context *select_ev, struct timeval *tvalp)
 {
-       fd_set r_fds, w_fds;
+       fd_set r_fds, w_fds, e_fds;
        struct tevent_fd *fde;
        int selrtn;
        int select_errno;
@@ -153,16 +151,22 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
 
        FD_ZERO(&r_fds);
        FD_ZERO(&w_fds);
+       FD_ZERO(&e_fds);
 
        /* setup any fd events */
        for (fde = select_ev->ev->fd_events; fde; fde = fde->next) {
                if (fde->fd < 0 || fde->fd >= FD_SETSIZE) {
+                       tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL,
+                                    "ERROR: EBADF fd[%d] >= %d "
+                                    "select_event_loop_once\n",
+                                    fde->fd, FD_SETSIZE);
                        errno = EBADF;
                        return -1;
                }
 
                if (fde->flags & TEVENT_FD_READ) {
                        FD_SET(fde->fd, &r_fds);
+                       FD_SET(fde->fd, &e_fds);
                }
                if (fde->flags & TEVENT_FD_WRITE) {
                        FD_SET(fde->fd, &w_fds);
@@ -175,7 +179,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
        }
 
        tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
-       selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
+       selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, &e_fds, tvalp);
        select_errno = errno;
        tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_AFTER_WAIT);
 
@@ -193,7 +197,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
                   fatal error. */
                tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL,
                             "ERROR: EBADF on select_event_loop_once\n");
-               select_ev->exit_code = EBADF;
+               errno = select_errno;
                return -1;
        }
 
@@ -217,6 +221,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
                                flags |= TEVENT_FD_WRITE;
                        }
                        if (flags) {
+                               DLIST_DEMOTE(select_ev->ev->fd_events, fde);
                                fde->handler(select_ev->ev, fde, flags, fde->private_data);
                                break;
                        }
@@ -231,8 +236,9 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
 */
 static int select_event_loop_once(struct tevent_context *ev, const char *location)
 {
-       struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
-                                                          struct select_event_context);
+       struct select_event_context *select_ev =
+               talloc_get_type_abort(ev->additional_data,
+               struct select_event_context);
        struct timeval tval;
 
        if (ev->signal_events &&
@@ -240,6 +246,10 @@ static int select_event_loop_once(struct tevent_context *ev, const char *locatio
                return 0;
        }
 
+       if (ev->threaded_contexts != NULL) {
+               tevent_common_threaded_activate_immediate(ev);
+       }
+
        if (ev->immediate_events &&
            tevent_common_loop_immediate(ev)) {
                return 0;
@@ -259,7 +269,7 @@ static const struct tevent_ops select_event_ops = {
        .set_fd_close_fn        = tevent_common_fd_set_close_fn,
        .get_fd_flags           = tevent_common_fd_get_flags,
        .set_fd_flags           = tevent_common_fd_set_flags,
-       .add_timer              = tevent_common_add_timer,
+       .add_timer              = tevent_common_add_timer_v2,
        .schedule_immediate     = tevent_common_schedule_immediate,
        .add_signal             = tevent_common_add_signal,
        .loop_once              = select_event_loop_once,