]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] session: call iohandler for embedded tasks (applets)
authorWilly Tarreau <w@1wt.eu>
Sat, 5 Sep 2009 18:57:35 +0000 (20:57 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 23 Sep 2009 21:52:15 +0000 (23:52 +0200)
Currently, it's up to process_session() to call the internal tasks
if any are associated to the task being processed. If such a task
is referenced, we don't use ->update() in process_session(), but
only ->iohandler(), which itself is free to use ->update() to
complete its work.

It it also important to understand that an I/O handler may wake the
task up again, for instance because it tries to send data to the
other stream interface, which itself will wake the task up. So
after returning from ->iohandler(), we must check if the task has
been sent back to the runqueue, and if so, immediately return.

src/session.c

index d085f16ea5bfcac210442fc6c246175880d3d2b1..f9b7157944e5bd56428d9eb7b571e2c6202e0bf2 100644 (file)
@@ -1173,10 +1173,10 @@ resync_stream_interface:
                if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
                        session_process_counters(s);
 
-               if (s->rep->cons->state == SI_ST_EST)
+               if (s->rep->cons->state == SI_ST_EST && !s->rep->cons->iohandler)
                        s->rep->cons->update(s->rep->cons);
 
-               if (s->req->cons->state == SI_ST_EST)
+               if (s->req->cons->state == SI_ST_EST && !s->req->cons->iohandler)
                        s->req->cons->update(s->req->cons);
 
                s->req->flags &= ~(BF_READ_NULL|BF_READ_PARTIAL|BF_WRITE_NULL|BF_WRITE_PARTIAL);
@@ -1200,6 +1200,21 @@ resync_stream_interface:
                        s->req->rex = TICK_ETERNITY;
                }
 
+               /* Call the second stream interface's I/O handler if it's embedded.
+                * Note that this one may wake the task up again.
+                */
+               if (s->req->cons->iohandler) {
+                       s->req->cons->iohandler(s->req->cons);
+                       if (task_in_rq(t)) {
+                               /* If we woke up, we don't want to requeue the
+                                * task to the wait queue, but rather requeue
+                                * it into the runqueue ASAP.
+                                */
+                               t->expire = TICK_ETERNITY;
+                               return t;
+                       }
+               }
+
                t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
                                       tick_first(s->rep->rex, s->rep->wex));
                if (s->req->analysers)