tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
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_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
+tevent_common_wakeup: int (struct tevent_context *)
+tevent_common_wakeup_init: int (struct tevent_context *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
return ret;
}
+bool tevent_common_have_events(struct tevent_context *ev)
+{
+ if (ev->fd_events != NULL) {
+ if (ev->fd_events != ev->pipe_fde) {
+ return true;
+ }
+ if (ev->fd_events->next != NULL) {
+ return true;
+ }
+
+ /*
+ * At this point we just have the wakeup pipe event as
+ * the only fd_event. That one does not count as a
+ * regular event, so look at the other event types.
+ */
+ }
+
+ return ((ev->timer_events != NULL) ||
+ (ev->immediate_events != NULL) ||
+ (ev->signal_events != NULL));
+}
+
/*
return on failure or (with 0) if all fd events are removed
*/
/*
* loop as long as we have events pending
*/
- while (ev->fd_events ||
- ev->timer_events ||
- ev->immediate_events ||
- ev->signal_events) {
+ while (tevent_common_have_events(ev)) {
int ret;
ret = _tevent_loop_once(ev, location);
if (ret != 0) {
return ev->ops->context_init(ev);
}
+
+static void wakeup_pipe_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *_private)
+{
+ ssize_t ret;
+
+ char c[16];
+ /* its non-blocking, doesn't matter if we read too much */
+ do {
+ ret = read(fde->fd, c, sizeof(c));
+ } while (ret == -1 && errno == EINTR);
+}
+
+/*
+ * Initialize the wakeup pipe and pipe fde
+ */
+
+int tevent_common_wakeup_init(struct tevent_context *ev)
+{
+ int ret;
+
+ if (ev->pipe_fde != NULL) {
+ return 0;
+ }
+
+ ret = pipe(ev->pipe_fds);
+ if (ret == -1) {
+ return errno;
+ }
+ ev_set_blocking(ev->pipe_fds[0], false);
+ ev_set_blocking(ev->pipe_fds[1], false);
+
+ ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0],
+ TEVENT_FD_READ,
+ wakeup_pipe_handler, NULL);
+ if (ev->pipe_fde == NULL) {
+ close(ev->pipe_fds[0]);
+ close(ev->pipe_fds[1]);
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+int tevent_common_wakeup(struct tevent_context *ev)
+{
+ ssize_t ret;
+
+ if (ev->pipe_fds[1] == -1) {
+ return ENOTCONN;
+ }
+
+ do {
+ char c = '\0';
+ ret = write(ev->pipe_fds[1], &c, 1);
+ } while ((ret == -1) && (errno == EINTR));
+
+ return 0;
+}
const char *location);
bool tevent_common_loop_immediate(struct tevent_context *ev);
+bool tevent_common_have_events(struct tevent_context *ev);
+int tevent_common_wakeup_init(struct tevent_context *ev);
+int tevent_common_wakeup(struct tevent_context *ev);
+
struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
int signum,
/*
* loop as long as we have events pending
*/
- while (ev->fd_events ||
- ev->timer_events ||
- ev->immediate_events ||
- ev->signal_events ||
+ while (tevent_common_have_events(ev) ||
poll_ev->fresh ||
poll_ev->disabled) {
int ret;
*/
static void tevent_common_signal_handler(int signum)
{
- char c = 0;
struct tevent_common_signal_list *sl;
struct tevent_context *ev = NULL;
int saved_errno = errno;
/* Write to each unique event context. */
for (sl = sig_state->sig_handlers[signum]; sl; sl = sl->next) {
if (sl->se->event_ctx && sl->se->event_ctx != ev) {
- ssize_t ret;
-
ev = sl->se->event_ctx;
- /* doesn't matter if this pipe overflows */
- do {
- ret = write(ev->pipe_fds[1], &c, 1);
- } while (ret == -1 && errno == EINTR);
+ tevent_common_wakeup(ev);
}
}
struct tevent_context *ev = se->event_ctx;
DLIST_REMOVE(ev->signal_events, se);
-
- if (ev->signal_events == NULL && ev->pipe_fde != NULL) {
- /*
- * This was the last signal. Destroy the pipe.
- */
- TALLOC_FREE(ev->pipe_fde);
-
- close(ev->pipe_fds[0]);
- close(ev->pipe_fds[1]);
- }
}
talloc_free(sl);
return 0;
}
-/*
- this is part of the pipe hack needed to avoid the signal race condition
-*/
-static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
- uint16_t flags, void *_private)
-{
- ssize_t ret;
-
- char c[16];
- /* its non-blocking, doesn't matter if we read too much */
- do {
- ret = read(fde->fd, c, sizeof(c));
- } while (ret == -1 && errno == EINTR);
-}
-
/*
add a signal event
return NULL on failure (memory allocation error)
struct tevent_signal *se;
struct tevent_common_signal_list *sl;
sigset_t set, oldset;
+ int ret;
+
+ ret = tevent_common_wakeup_init(ev);
+ if (ret != 0) {
+ errno = ret;
+ return NULL;
+ }
if (signum >= TEVENT_NUM_SIGNALS) {
errno = EINVAL;
return NULL;
}
- /* we need to setup the pipe hack handler if not already
- setup */
- if (ev->pipe_fde == NULL) {
- if (pipe(ev->pipe_fds) == -1) {
- talloc_free(se);
- return NULL;
- }
- ev_set_blocking(ev->pipe_fds[0], false);
- ev_set_blocking(ev->pipe_fds[1], false);
- ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0],
- TEVENT_FD_READ,
- signal_pipe_handler, NULL);
- if (!ev->pipe_fde) {
- close(ev->pipe_fds[0]);
- close(ev->pipe_fds[1]);
- talloc_free(se);
- return NULL;
- }
- }
-
/* only install a signal handler if not already installed */
if (sig_state->sig_handlers[signum] == NULL) {
struct sigaction act;