summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-01-31 08:18:52 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:25 -0500
commit58d6c73e946d11574a6220f37887e1cdfe05f525 (patch)
tree6d26d4ee20261610328bee5f513f7df1171dfa8e /source4/lib
parent26bf3063d3250aba60ba458efd131e5a24006363 (diff)
downloadsamba-58d6c73e946d11574a6220f37887e1cdfe05f525.tar.gz
samba-58d6c73e946d11574a6220f37887e1cdfe05f525.tar.bz2
samba-58d6c73e946d11574a6220f37887e1cdfe05f525.zip
r5123: fixed a bug in the timed events handling. It was possible for a timed
event handler to trigger a free that could cause a timer to be triggered twice. This changs fixes it properly by marking timer events to be removed using a zero next_event time. I also changed the default timeout for events.c to be infinite, so if there are no events to handle then smbd will sit forever doing nothing. That allows it to be swapped out completely when idle. (This used to be commit 0f1fb7017ee441cbebcad45900435adb57ca1760)
Diffstat (limited to 'source4/lib')
-rw-r--r--source4/lib/events.c29
-rw-r--r--source4/lib/time.c8
2 files changed, 26 insertions, 11 deletions
diff --git a/source4/lib/events.c b/source4/lib/events.c
index 98c2b9cfa8..3263be08f1 100644
--- a/source4/lib/events.c
+++ b/source4/lib/events.c
@@ -221,7 +221,7 @@ int event_loop_once(struct event_context *ev)
fd_set r_fds, w_fds;
struct fd_event *fe;
struct loop_event *le;
- struct timed_event *te;
+ struct timed_event *te, *te_next;
int selrtn;
struct timeval tval, t;
uint32_t destruction_count = ev->destruction_count;
@@ -253,13 +253,24 @@ int event_loop_once(struct event_context *ev)
}
/* start with a reasonable max timeout */
- tval.tv_sec = 600;
+ tval.tv_sec = 0;
tval.tv_usec = 0;
/* work out the right timeout for all timed events */
- for (te=ev->timed_events;te;te=te->next) {
- struct timeval tv = timeval_diff(&te->next_event, &t);
- tval = timeval_min(&tv, &tval);
+ for (te=ev->timed_events;te;te=te_next) {
+ struct timeval tv;
+ te_next = te->next;
+ if (timeval_is_zero(&te->next_event)) {
+ talloc_free(te);
+ continue;
+ }
+
+ tv = timeval_diff(&te->next_event, &t);
+ if (timeval_is_zero(&tval)) {
+ tval = tv;
+ } else {
+ tval = timeval_min(&tv, &tval);
+ }
}
/* only do a select() if there're fd_events
@@ -316,18 +327,14 @@ int event_loop_once(struct event_context *ev)
for (te=ev->timed_events;te;) {
struct timed_event *next = te->next;
if (timeval_compare(&te->next_event, &t) >= 0) {
+ te->next_event = timeval_zero();
te->handler(ev, te, t);
if (destruction_count != ev->destruction_count) {
break;
}
- if (timeval_compare(&te->next_event, &t) >= 0) {
- /* the handler didn't set a time for the
- next event - remove the event */
- talloc_free(te);
- }
}
te = next;
- }
+ }
return 0;
}
diff --git a/source4/lib/time.c b/source4/lib/time.c
index e214179b6c..7a4059f646 100644
--- a/source4/lib/time.c
+++ b/source4/lib/time.c
@@ -402,6 +402,14 @@ struct timeval timeval_zero(void)
}
/*
+ return True if a timeval is zero
+*/
+BOOL timeval_is_zero(struct timeval *tv)
+{
+ return tv->tv_sec == 0 && tv->tv_usec == 0;
+}
+
+/*
return a timeval for the current time
*/
struct timeval timeval_current(void)