tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
tevent_context_is_wrapper: bool (struct tevent_context *)
tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *)
+tevent_context_set_wait_timeout: uint32_t (struct tevent_context *, uint32_t)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_get_tag: uint64_t (const struct tevent_fd *)
ev->ops = ops;
ev->additional_data = additional_data;
+ /*
+ * have a default tick time of 30 seconds. This guarantees
+ * that code that uses its own timeout checking will be
+ * able to proceed eventually
+ */
+ tevent_context_set_wait_timeout(ev, 30);
+
ret = ev->ops->context_init(ev);
if (ret != 0) {
talloc_free(ev);
return tevent_context_init_byname(mem_ctx, NULL);
}
+uint32_t tevent_context_set_wait_timeout(struct tevent_context *ev,
+ uint32_t secs)
+{
+ time_t ret = ev->wait_timeout.tv_sec;
+
+ /*
+ * Cut to signed 32-bit time_t. This is the maximum that we
+ * can reasonably expect to fit into time_t. Use that as magic
+ * value for "wait forever". Nobody wants to wait 68 years....
+ */
+ secs = MIN(secs, INT32_MAX);
+
+ /*
+ * "secs == 0" and thus wait_timeout==tevent_timeval_zero()
+ * might have a special meaning for custom tevent loop_once
+ * backend functions. Make this an invalid value, our
+ * internal poll and epoll backends deal with this properly,
+ * see tevent_common_no_timeout()
+ */
+ ev->wait_timeout = tevent_timeval_set((time_t)secs,
+ (secs == 0) ? INT32_MAX: 0);
+
+ return ret;
+}
+
/*
add a fd based event
return NULL on failure (memory allocation error)
*/
void tevent_set_default_backend(const char *backend);
+/**
+ * @brief Set the default time to wait without tevent_timers pending
+ *
+ * Setting the wait timeout to 0 means polling behaviour, e.g.
+ * tevent_loop_once will return -1/errno=EAGAIN, when all
+ * currently available events were processes.
+ *
+ * Setting it to UINT32_MAX makes tevent_loop_once wait forever.
+ * The default is 30 seconds.
+ *
+ * @param[in] ev The tevent context to set this on
+ *
+ * @param[in] secs The number of seconds to wait without timers
+ *
+ * @return secs The previous wait_timeout value
+ */
+uint32_t tevent_context_set_wait_timeout(struct tevent_context *ev,
+ uint32_t secs);
+
#ifdef DOXYGEN
/**
* @brief Add a file descriptor based event.
int ret, i;
#define MAXEVENTS 1
struct epoll_event events[MAXEVENTS];
- int timeout = -1;
+ int timeout = tevent_common_timeout_msec(tvalp);
int wait_errno;
- if (tvalp) {
- /* it's better to trigger timed events a bit later than too early */
- timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
- }
-
if (epoll_ev->ev->signal_events &&
tevent_common_check_signal(epoll_ev->ev)) {
return 0;
}
if (ret == 0 && tvalp) {
+ /*
+ * tevent_context_set_wait_timeout(0) was used.
+ */
+ if (tevent_common_no_timeout(tvalp)) {
+ errno = EAGAIN;
+ return -1;
+ }
+
/* we don't care about a possible delay here */
tevent_common_loop_timer_delay(epoll_ev->ev);
return 0;
* tevent_common_add_timer_v2()
*/
struct tevent_timer *last_zero_timer;
+ struct timeval wait_timeout;
#ifdef HAVE_PTHREAD
struct tevent_context *prev, *next;
const char *handler_name,
const char *location);
struct timeval tevent_common_loop_timer_delay(struct tevent_context *);
+
+/* timeout values for poll(2) / epoll_wait(2) */
+static inline bool tevent_common_no_timeout(const struct timeval *tv)
+{
+ if ((tv->tv_sec == 0) && (tv->tv_usec == INT32_MAX)) {
+ /*
+ * This is special from
+ * tevent_context_set_wait_timeout(0)
+ */
+ return true;
+ }
+ return false;
+}
+static inline int tevent_common_timeout_msec(const struct timeval *tv)
+{
+ if (tv->tv_sec == INT32_MAX) {
+ return -1;
+ }
+ if (tevent_common_no_timeout(tv)) {
+ /*
+ * This is special from
+ * tevent_context_set_wait_timeout(0)
+ */
+ return 0;
+ }
+ return ((tv->tv_usec + 999) / 1000) + (tv->tv_sec * 1000);
+}
+
int tevent_common_invoke_timer_handler(struct tevent_timer *te,
struct timeval current_time,
bool *removed);
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
int pollrtn;
- int timeout = -1;
+ int timeout = tevent_common_timeout_msec(tvalp);
int poll_errno;
struct tevent_fd *fde = NULL;
struct tevent_fd *next = NULL;
return 0;
}
- if (tvalp != NULL) {
- timeout = tvalp->tv_sec * 1000;
- timeout += (tvalp->tv_usec + 999) / 1000;
- }
-
ok = poll_event_sync_arrays(ev, poll_ev);
if (!ok) {
return -1;
}
if (pollrtn == 0 && tvalp) {
+ /*
+ * tevent_context_set_wait_timeout(0) was used.
+ */
+ if (tevent_common_no_timeout(tvalp)) {
+ errno = EAGAIN;
+ return -1;
+ }
+
/* we don't care about a possible delay here */
tevent_common_loop_timer_delay(ev);
return 0;
int ret;
if (!te) {
- /* have a default tick time of 30 seconds. This guarantees
- that code that uses its own timeout checking will be
- able to proceed eventually */
- return tevent_timeval_set(30, 0);
+ return ev->wait_timeout;
}
/*
delay = tevent_timeval_until(¤t_time, &te->next_event);
if (!tevent_timeval_is_zero(&delay)) {
+ if (tevent_common_no_timeout(&ev->wait_timeout)) {
+ return ev->wait_timeout;
+ }
return delay;
}
}