MINOR: threads/server: Add a lock to deal with insert in updates_servers list
This list is used to save changes on the servers state. So when serveral threads
are used, it must be locked. The changes are then applied in the sync-point. To
do so, servers_update_status has be moved in the sync-point. So this is useless
to lock it at this step because the sync-point is a protected area by iteself.
diff --git a/src/haproxy.c b/src/haproxy.c
index f905473..5710cc2 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2247,6 +2247,7 @@
/* *** { */
/* Put here all sync functions */
+ servers_update_status(); /* Commit server status changes */
/* *** } */
exit:
@@ -2282,8 +2283,6 @@
fd_process_cached_events();
applet_run_active();
- /* Commit server status changes */
- servers_update_status();
/* Synchronize all polling loops */
sync_poll_loop();
diff --git a/src/server.c b/src/server.c
index b6986a9..648f3dd 100644
--- a/src/server.c
+++ b/src/server.c
@@ -46,6 +46,11 @@
struct list updated_servers = LIST_HEAD_INIT(updated_servers);
+#ifdef USE_THREAD
+HA_SPINLOCK_T updated_servers_lock;
+#endif
+
+static void srv_register_update(struct server *srv);
static void srv_update_state(struct server *srv, int version, char **params);
static int srv_apply_lastaddr(struct server *srv, int *err_code);
static int srv_set_fqdn(struct server *srv, const char *fqdn);
@@ -761,11 +766,9 @@
{
struct stream *stream, *stream_bck;
- SPIN_LOCK(SERVER_LOCK, &srv->lock);
list_for_each_entry_safe(stream, stream_bck, &srv->actconns, by_srv)
if (stream->srv_conn == srv)
stream_shutdown(stream, why);
- SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
}
/* Shutdown all connections of all backup servers of a proxy. The caller must
@@ -876,10 +879,7 @@
s->op_st_chg.duration = check->duration;
}
- /* Register changes to be applied asynchronously */
- if (LIST_ISEMPTY(&s->update_status))
- LIST_ADDQ(&updated_servers, &s->update_status);
-
+ srv_register_update(s);
for (srv = s->trackers; srv; srv = srv->tracknext)
srv_set_stopped(srv, NULL, NULL);
}
@@ -918,10 +918,7 @@
if (s->slowstart <= 0)
s->next_state = SRV_ST_RUNNING;
- /* Register changes to be applied asynchronously */
- if (LIST_ISEMPTY(&s->update_status))
- LIST_ADDQ(&updated_servers, &s->update_status);
-
+ srv_register_update(s);
for (srv = s->trackers; srv; srv = srv->tracknext)
srv_set_running(srv, NULL, NULL);
}
@@ -959,10 +956,7 @@
s->op_st_chg.duration = check->duration;
}
- /* Register changes to be applied asynchronously */
- if (LIST_ISEMPTY(&s->update_status))
- LIST_ADDQ(&updated_servers, &s->update_status);
-
+ srv_register_update(s);
for (srv = s->trackers; srv; srv = srv->tracknext)
srv_set_stopping(srv, NULL, NULL);
}
@@ -990,9 +984,7 @@
if (cause)
strlcpy2(s->adm_st_chg_cause, cause, sizeof(s->adm_st_chg_cause));
- /* Register changes to be applied asynchronously */
- if (LIST_ISEMPTY(&s->update_status))
- LIST_ADDQ(&updated_servers, &s->update_status);
+ srv_register_update(s);
/* stop going down if the equivalent flag was already present (forced or inherited) */
if (((mode & SRV_ADMF_MAINT) && (s->next_admin & ~mode & SRV_ADMF_MAINT)) ||
@@ -1028,9 +1020,8 @@
s->next_admin &= ~mode;
- /* Register changes to be applied asynchronously */
- if (LIST_ISEMPTY(&s->update_status))
- LIST_ADDQ(&updated_servers, &s->update_status);
+ srv_register_update(s);
+
/* stop going down if the equivalent flag is still present (forced or inherited) */
if (((mode & SRV_ADMF_MAINT) && (s->next_admin & SRV_ADMF_MAINT)) ||
((mode & SRV_ADMF_DRAIN) && (s->next_admin & SRV_ADMF_DRAIN)))
@@ -1146,9 +1137,7 @@
sv->next_eweight = (sv->uweight * w + px->lbprm.wmult - 1) / px->lbprm.wmult;
- /* Register changes to be applied asynchronously */
- if (LIST_ISEMPTY(&sv->update_status))
- LIST_ADDQ(&updated_servers, &sv->update_status);
+ srv_register_update(sv);
}
/*
@@ -2589,6 +2578,18 @@
return NULL;
}
+/* Registers changes to be applied asynchronously */
+static void srv_register_update(struct server *srv)
+{
+ if (LIST_ISEMPTY(&srv->update_status)) {
+ THREAD_WANT_SYNC();
+ SPIN_LOCK(UPDATED_SERVERS_LOCK, &updated_servers_lock);
+ if (LIST_ISEMPTY(&srv->update_status))
+ LIST_ADDQ(&updated_servers, &srv->update_status);
+ SPIN_UNLOCK(UPDATED_SERVERS_LOCK, &updated_servers_lock);
+ }
+}
+
/* Update a server state using the parameters available in the params list */
static void srv_update_state(struct server *srv, int version, char **params)
{
@@ -4371,6 +4372,7 @@
__attribute__((constructor))
static void __server_init(void)
{
+ SPIN_INIT(&updated_servers_lock);
cli_register_kw(&cli_kws);
}
@@ -4880,6 +4882,9 @@
/*
* This function loops on servers registered for asynchronous
* status changes
+ *
+ * NOTE: No needs to lock <updated_servers> list because it is called inside the
+ * sync point.
*/
void servers_update_status(void) {
struct server *s, *stmp;