]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: poll: only rely on wake_expired_tasks() to compute the wait delay
authorThierry FOURNIER <tfournier@haproxy.com>
Mon, 15 Dec 2014 12:26:01 +0000 (13:26 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 28 Feb 2015 22:12:30 +0000 (23:12 +0100)
Actually, HAProxy uses the function "process_runnable_tasks" and
"wake_expired_tasks" to get the next task which can expires.

If a task is added with "task_schedule" or other method during
the execution of an other task, the expiration of this new task
is not taken into account, and the execution of this task can be
too late.

Actualy, HAProxy seems to be no sensitive to this bug.

This fix moves the call to process_runnable_tasks() before the timeout
calculation and ensures that all wakeups are processed together. Only
wake_expired_tasks() needs to return a timeout now.

include/proto/task.h
src/haproxy.c
src/task.c

index 76f77c87eb3e32ab3e6045378f974bd08e5e72e2..107c961a517244147adf9c8bae793c00284e7243 100644 (file)
@@ -259,13 +259,13 @@ static inline void task_schedule(struct task *task, int when)
  *   - return the date of next event in <next> or eternity.
  */
 
-void process_runnable_tasks(int *next);
+void process_runnable_tasks();
 
 /*
  * Extract all expired timers from the timer queue, and wakes up all
  * associated tasks. Returns the date of next event (or eternity).
  */
-void wake_expired_tasks(int *next);
+int wake_expired_tasks();
 
 /* Perform minimal initializations, report 0 in case of error, 1 if OK. */
 int init_task();
index c5ffa0fb954caf9cc216eba607b283af63a188df..f50deff952cfdcf58e5ad30033fcb0f8fa8f8b7d 100644 (file)
@@ -1459,14 +1459,14 @@ void run_poll_loop()
 
        tv_update_date(0,1);
        while (1) {
+               /* Process a few tasks */
+               process_runnable_tasks();
+
                /* check if we caught some signals and process them */
                signal_process_queue();
 
                /* Check if we can expire some tasks */
-               wake_expired_tasks(&next);
-
-               /* Process a few tasks */
-               process_runnable_tasks(&next);
+               next = wake_expired_tasks();
 
                /* stop when there's nothing left to do */
                if (jobs == 0)
index 74ae1c9a77f64f3e3d62dbcc530f0b3f49f56547..4985aa22a96eab58c793607e1ef2f4df570b0fa6 100644 (file)
@@ -118,9 +118,9 @@ void __task_queue(struct task *task)
 
 /*
  * Extract all expired timers from the timer queue, and wakes up all
- * associated tasks. Returns the date of next event (or eternity) in <next>.
+ * associated tasks. Returns the date of next event (or eternity).
  */
-void wake_expired_tasks(int *next)
+int wake_expired_tasks()
 {
        struct task *task;
        struct eb32_node *eb;
@@ -139,8 +139,7 @@ void wake_expired_tasks(int *next)
 
                if (likely(tick_is_lt(now_ms, eb->key))) {
                        /* timer not expired yet, revisit it later */
-                       *next = eb->key;
-                       return;
+                       return eb->key;
                }
 
                /* timer looks expired, detach it from the queue */
@@ -172,9 +171,8 @@ void wake_expired_tasks(int *next)
                task_wakeup(task, TASK_WOKEN_TIMER);
        }
 
-       /* We have found no task to expire in any tree */
-       *next = TICK_ETERNITY;
-       return;
+       /* No task is expired */
+       return TICK_ETERNITY;
 }
 
 /* The run queue is chronologically sorted in a tree. An insertion counter is
@@ -187,11 +185,10 @@ void wake_expired_tasks(int *next)
  *
  * The function adjusts <next> if a new event is closer.
  */
-void process_runnable_tasks(int *next)
+void process_runnable_tasks()
 {
        struct task *t;
        unsigned int max_processed;
-       int expire;
 
        run_queue_cur = run_queue; /* keep a copy for reporting */
        nb_tasks_cur = nb_tasks;
@@ -206,8 +203,6 @@ void process_runnable_tasks(int *next)
        if (likely(niced_tasks))
                max_processed = (max_processed + 3) / 4;
 
-       expire = *next;
-
        while (max_processed--) {
                /* Note: this loop is one of the fastest code path in
                 * the whole program. It should not be re-arranged
@@ -245,13 +240,10 @@ void process_runnable_tasks(int *next)
 
                if (likely(t != NULL)) {
                        t->state &= ~TASK_RUNNING;
-                       if (t->expire) {
+                       if (t->expire)
                                task_queue(t);
-                               expire = tick_first_2nz(expire, t->expire);
-                       }
                }
        }
-       *next = expire;
 }
 
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */