A live worker frees its thread-local diagnostic buffers before EXTRA_OBJS
teardown, whose deinitializers can still emit diagnostics.
ha_free() releases the allocation and clears only the area pointer. It
leaves size, head and data unchanged, while b_is_null() tests size rather
than area. A previously allocated buffer therefore still looks allocated
with a NULL area. Later diagnostics skip lazy allocation and can crash
when accessing the buffer.
Reset both usermsgs_buf and usermsgs_ctx.str to BUF_NULL after freeing
their areas. This clears the stale size and contents metadata so later
diagnostics can allocate fresh buffers. The post-deinit cleanup releases
any buffers reallocated during EXTRA_OBJS teardown.
This could be backported in every maintained versions.
ring_free(_HA_ATOMIC_XCHG(&startup_logs, NULL));
ha_free(&usermsgs_buf.area);
ha_free(&usermsgs_ctx.str.area);
+ /* Ensure b_is_null() recognizes the freed buffers. */
+ usermsgs_buf = BUF_NULL;
+ usermsgs_ctx.str = BUF_NULL;
}
/* errors might be used in threads and even before forking, thus 2 deinit */