From: Willy Tarreau Date: Sat, 5 Sep 2009 18:57:35 +0000 (+0200) Subject: [MEDIUM] session: call iohandler for embedded tasks (applets) X-Git-Tag: v1.4-dev3~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1accfc0d3a4779f7dac9eebb12f3d3b4c3653fcb;p=thirdparty%2Fhaproxy.git [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 d085f16ea5..f9b7157944 100644 --- a/src/session.c +++ b/src/session.c @@ -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)