While reviewing HTTP/2 MUX timeout, it seems there is a possibility that
MUX task is requeued via h2c_update_timeout() with an already expired
date. This can happens with idle connections on two cases :
* first with shut timeout, as timer is not refreshed if already set
* second with http-request and keep-alive timers, which are based on
idle_start
Queuing an already expired task is an undefined behavior. Fix this by
using task_wakeup() instead of task_queue() at the end of
h2c_update_timeout() if such case occurs.
This should be backported up to 2.6.
} else {
h2c->task->expire = TICK_ETERNITY;
}
+
+ /* Timer may already be expired, in this case it must not be requeued.
+ * Currently it may happen with idle conn calculation based on shut or
+ * http-req/ka timeouts.
+ */
+ if (unlikely(tick_is_expired(h2c->task->expire, now_ms))) {
+ task_wakeup(h2c->task, TASK_WOKEN_TIMER);
+ goto leave;
+ }
+
task_queue(h2c->task);
leave:
TRACE_LEAVE(H2_EV_H2C_WAKE);