[MEDIUM] session: call iohandler for embedded tasks (applets)
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.
diff --git a/src/session.c b/src/session.c
index d085f16..f9b7157 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1173,10 +1173,10 @@
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 @@
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)