dovecot-2.2: ioloop: Delay actual start of a new normal timeout ...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Aug 27 08:41:28 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/ec6e672a6e32
changeset: 19019:ec6e672a6e32
user: Stephan Bosch <stephan at rename-it.nl>
date: Thu Aug 27 10:39:26 2015 +0200
description:
ioloop: Delay actual start of a new normal timeout until the next io_loop_run() cycle.
This makes sure that timeouts will not expire before they get a chance to
run.
diffstat:
src/lib/Makefile.am | 1 +
src/lib/ioloop-private.h | 2 +
src/lib/ioloop.c | 57 +++++++++++++++++++++++++++++++++++++++++++++--
src/lib/test-ioloop.c | 42 +++++++++++++++++++++++++++++++++++
src/lib/test-lib.c | 1 +
src/lib/test-lib.h | 1 +
6 files changed, 101 insertions(+), 3 deletions(-)
diffs (219 lines):
diff -r f363a7665a14 -r ec6e672a6e32 src/lib/Makefile.am
--- a/src/lib/Makefile.am Wed Aug 26 17:00:55 2015 +0200
+++ b/src/lib/Makefile.am Thu Aug 27 10:39:26 2015 +0200
@@ -304,6 +304,7 @@
test-hash-format.c \
test-hash-method.c \
test-hex-binary.c \
+ test-ioloop.c \
test-iso8601-date.c \
test-istream.c \
test-istream-base64-decoder.c \
diff -r f363a7665a14 -r ec6e672a6e32 src/lib/ioloop-private.h
--- a/src/lib/ioloop-private.h Wed Aug 26 17:00:55 2015 +0200
+++ b/src/lib/ioloop-private.h Thu Aug 27 10:39:26 2015 +0200
@@ -3,6 +3,7 @@
#include "priorityq.h"
#include "ioloop.h"
+#include "array-decl.h"
#ifndef IOLOOP_INITIAL_FD_COUNT
# define IOLOOP_INITIAL_FD_COUNT 128
@@ -16,6 +17,7 @@
struct io_file *io_files;
struct io_file *next_io_file;
struct priorityq *timeouts;
+ ARRAY(struct timeout *) timeouts_new;
struct ioloop_handler_context *handler_context;
struct ioloop_notify_handler_context *notify_handler_context;
diff -r f363a7665a14 -r ec6e672a6e32 src/lib/ioloop.c
--- a/src/lib/ioloop.c Wed Aug 26 17:00:55 2015 +0200
+++ b/src/lib/ioloop.c Thu Aug 27 10:39:26 2015 +0200
@@ -204,7 +204,8 @@
struct timeout *timeout;
timeout = i_new(struct timeout, 1);
- timeout->source_linenum = source_linenum;
+ timeout->item.idx = UINT_MAX;
+ timeout->source_linenum = source_linenum;
timeout->ioloop = current_ioloop;
timeout->callback = callback;
@@ -227,9 +228,15 @@
timeout = timeout_add_common(source_linenum, callback, context);
timeout->msecs = msecs;
- timeout_update_next(timeout, timeout->ioloop->running ?
+ if (msecs > 0) {
+ /* start this timeout in the next run cycle */
+ array_append(&timeout->ioloop->timeouts_new, &timeout, 1);
+ } else {
+ /* trigger zero timeouts as soon as possible */
+ timeout_update_next(timeout, timeout->ioloop->running ?
NULL : &ioloop_timeval);
- priorityq_add(timeout->ioloop->timeouts, &timeout->item);
+ priorityq_add(timeout->ioloop->timeouts, &timeout->item);
+ }
return timeout;
}
@@ -282,10 +289,21 @@
void timeout_remove(struct timeout **_timeout)
{
struct timeout *timeout = *_timeout;
+ struct ioloop *ioloop = timeout->ioloop;
*_timeout = NULL;
if (timeout->item.idx != UINT_MAX)
priorityq_remove(timeout->ioloop->timeouts, &timeout->item);
+ else {
+ struct timeout *const *to_idx;
+ array_foreach(&ioloop->timeouts_new, to_idx) {
+ if (*to_idx == timeout) {
+ array_delete(&ioloop->timeouts_new,
+ array_foreach_idx(&ioloop->timeouts_new, to_idx), 1);
+ break;
+ }
+ }
+ }
timeout_free(timeout);
}
@@ -393,6 +411,27 @@
}
}
+static void io_loop_timeouts_start_new(struct ioloop *ioloop)
+{
+ struct timeout *const *to_idx;
+
+ if (array_count(&ioloop->timeouts_new) == 0)
+ return;
+
+ io_loop_time_refresh();
+
+ array_foreach(&ioloop->timeouts_new, to_idx) {
+ struct timeout *timeout = *to_idx;
+ i_assert(timeout->next_run.tv_sec == 0 &&
+ timeout->next_run.tv_usec == 0);
+ i_assert(!timeout->one_shot);
+ i_assert(timeout->msecs > 0);
+ timeout_update_next(timeout, &ioloop_timeval);
+ priorityq_add(ioloop->timeouts, &timeout->item);
+ }
+ array_clear(&ioloop->timeouts_new);
+}
+
static void io_loop_timeouts_update(struct ioloop *ioloop, long diff_secs)
{
struct priorityq_item *const *items;
@@ -545,6 +584,7 @@
void io_loop_handler_run(struct ioloop *ioloop)
{
+ io_loop_timeouts_start_new(ioloop);
io_loop_handler_run_internal(ioloop);
io_loop_call_pending(ioloop);
}
@@ -587,6 +627,7 @@
ioloop = i_new(struct ioloop, 1);
ioloop->timeouts = priorityq_init(timeout_cmp, 32);
+ i_array_init(&ioloop->timeouts_new, 8);
ioloop->time_moved_callback = current_ioloop != NULL ?
current_ioloop->time_moved_callback :
@@ -600,6 +641,7 @@
void io_loop_destroy(struct ioloop **_ioloop)
{
struct ioloop *ioloop = *_ioloop;
+ struct timeout *const *to_idx;
struct priorityq_item *item;
*_ioloop = NULL;
@@ -622,6 +664,15 @@
}
i_assert(ioloop->io_pending_count == 0);
+ array_foreach(&ioloop->timeouts_new, to_idx) {
+ struct timeout *to = *to_idx;
+
+ i_warning("Timeout leak: %p (line %u)", (void *)to->callback,
+ to->source_linenum);
+ timeout_free(to);
+ }
+ array_free(&ioloop->timeouts_new);
+
while ((item = priorityq_pop(ioloop->timeouts)) != NULL) {
struct timeout *to = (struct timeout *)item;
diff -r f363a7665a14 -r ec6e672a6e32 src/lib/test-ioloop.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-ioloop.c Thu Aug 27 10:39:26 2015 +0200
@@ -0,0 +1,42 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "time-util.h"
+#include "ioloop.h"
+
+#include <unistd.h>
+
+static void timeout_callback(struct timeval *tv)
+{
+ if (gettimeofday(tv, NULL) < 0)
+ i_fatal("gettimeofday() failed: %m");
+ io_loop_stop(current_ioloop);
+}
+
+static void test_ioloop_timeout(void)
+{
+ struct ioloop *ioloop;
+ struct timeout *to;
+ struct timeval tv_start, tv_callback;
+
+ test_begin("ioloop timeout");
+
+ ioloop = io_loop_create();
+ sleep(1);
+ to = timeout_add(1000, timeout_callback, &tv_callback);
+ timeout_remove(&to);
+ to = timeout_add(1000, timeout_callback, &tv_callback);
+ if (gettimeofday(&tv_start, NULL) < 0)
+ i_fatal("gettimeofday() failed: %m");
+ io_loop_run(ioloop);
+ test_assert(timeval_diff_msecs(&tv_callback, &tv_start) >= 500);
+ timeout_remove(&to);
+ io_loop_destroy(&ioloop);
+
+ test_end();
+}
+
+void test_ioloop(void)
+{
+ test_ioloop_timeout();
+}
diff -r f363a7665a14 -r ec6e672a6e32 src/lib/test-lib.c
--- a/src/lib/test-lib.c Wed Aug 26 17:00:55 2015 +0200
+++ b/src/lib/test-lib.c Thu Aug 27 10:39:26 2015 +0200
@@ -20,6 +20,7 @@
test_hash_format,
test_hash_method,
test_hex_binary,
+ test_ioloop,
test_iso8601_date,
test_istream,
test_istream_base64_decoder,
diff -r f363a7665a14 -r ec6e672a6e32 src/lib/test-lib.h
--- a/src/lib/test-lib.h Wed Aug 26 17:00:55 2015 +0200
+++ b/src/lib/test-lib.h Thu Aug 27 10:39:26 2015 +0200
@@ -21,6 +21,7 @@
void test_hash_format(void);
void test_hash_method(void);
void test_hex_binary(void);
+void test_ioloop(void);
void test_iso8601_date(void);
void test_istream(void);
void test_istream_base64_decoder(void);
More information about the dovecot-cvs
mailing list