From 1e690bb6c49590cd3b4fae11c2f85f37e958635e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 22 Oct 2020 11:30:59 +0200 Subject: [PATCH] BUG/MEDIUM: server: support changing the slowstart value from state-file If the slowstart value in a state file implies the latest state change is within the slowstart period, we end up calling srv_update_status() to reschedule the server's state change but its task is not yet allocated and remains null, causing a crash on startup. Make sure srv_update_status() supports being called with partially initialized servers which do not yet have a task. If the task has to be scheduled, it will necessarily happen after initialization since it will result from a state change. This should be backported wherever server-state is present. --- src/server.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index 45b0f4121..2271f9e99 100644 --- a/src/server.c +++ b/src/server.c @@ -4630,7 +4630,9 @@ INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws); * This function applies server's status changes, it is * is designed to be called asynchronously. * - * Must be called with the server lock held. + * Must be called with the server lock held. This may also be called at init + * time as the result of parsing the state file, in which case no lock will be + * held, and the server's warmup task can be null. */ static void srv_update_status(struct server *s) { @@ -4730,7 +4732,7 @@ static void srv_update_status(struct server *s) s->down_time += now.tv_sec - s->last_change; s->last_change = now.tv_sec; - if (s->next_state == SRV_ST_STARTING) + if (s->next_state == SRV_ST_STARTING && s->warmup) task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)))); server_recalc_eweight(s, 0); @@ -4908,8 +4910,10 @@ static void srv_update_status(struct server *s) } else { s->next_state = SRV_ST_STARTING; - if (s->slowstart > 0) - task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)))); + if (s->slowstart > 0) { + if (s->warmup) + task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)))); + } else s->next_state = SRV_ST_RUNNING; }