From 04a4d242c9d3be576745ca3765ca2fbc3776b449 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Wed, 18 Feb 2026 17:04:03 +0100 Subject: [PATCH] BUG/MEDIUM: stats-file: fix shm-stats-file recover when all process slots are full MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Amaury reported that when the following warning is reported by haproxy: [WARNING]  (296347) : config: failed to get shm stats file slot for 'haproxy.stats', all slots are occupied haproxy would segfault right after during clock update operation. The reason for the warning being emitted is not the object of this commit (all shm-stats-file slots occupied by simultaneous co-processes) but since it was is intended that haproxy is able to keep working despite that warning (ignoring the use of shm-stats-file), we should fix the crash. The crash is caused by the fact that we detach from the shared memory while the global_now_ns and global_now_ms clock pointers still point to the shared memory. Instead we should revert to using our local clock instead before detaching from the map. It should be backported in 3.3 --- src/stats-file.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/stats-file.c b/src/stats-file.c index 73c13a637..99d3a03e8 100644 --- a/src/stats-file.c +++ b/src/stats-file.c @@ -840,6 +840,8 @@ next: int shm_stats_file_prepare(void) { struct task *heartbeat_task; + volatile ullong *local_global_now_ns; + volatile uint *local_global_now_ms; int first = 0; // process responsible for initializing the shm memory int slot; int objects; @@ -901,7 +903,11 @@ int shm_stats_file_prepare(void) else if (!shm_stats_file_check_ver(shm_stats_file_hdr)) goto err_version; - /* from now on use the shared global time */ + /* from now on use the shared global time, but save local global time + * in case reverting is required + */ + local_global_now_ms = global_now_ms; + local_global_now_ns = global_now_ns; global_now_ms = &shm_stats_file_hdr->global_now_ms; global_now_ns = &shm_stats_file_hdr->global_now_ns; @@ -968,7 +974,18 @@ int shm_stats_file_prepare(void) slot = shm_stats_file_get_free_slot(shm_stats_file_hdr); if (slot == -1) { ha_warning("config: failed to get shm stats file slot for '%s', all slots are occupied\n", global.shm_stats_file); + /* stop using shared clock since we withdraw from the shared memory, + * simply update the local clock and switch to using it instead + */ + *local_global_now_ms = HA_ATOMIC_LOAD(global_now_ms); + *local_global_now_ns = HA_ATOMIC_LOAD(global_now_ns); + + /* shared memory mapping no longer needed */ munmap(shm_stats_file_hdr, sizeof(*shm_stats_file_hdr)); + shm_stats_file_hdr = NULL; + + global_now_ms = local_global_now_ms; + global_now_ns = local_global_now_ns; return ERR_WARN; } -- 2.47.3