BUG/MEDIUM: server: support changing the slowstart value from state-file
authorWilly Tarreau <w@1wt.eu>
Thu, 22 Oct 2020 09:30:59 +0000 (11:30 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 3 Nov 2020 14:47:53 +0000 (15:47 +0100)
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.

(cherry picked from commit 1e690bb6c49590cd3b4fae11c2f85f37e958635e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 550a2f16abb0ef88e75b30c85319a989192de7cd)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/server.c

index 1233c67..b19e351 100644 (file)
@@ -4898,7 +4898,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)
 {
@@ -4998,7 +5000,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);
@@ -5174,8 +5176,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;
                        }