A jemalloc quirk may trigger an out-of-memory condition in named over time
Since version 5.0.0, decay-based purging is the only available dirty page cleanup mechanism in jemalloc. It relies on so-called tickers, which are simple data structures used for ensuring that certain actions are taken "once every N times". Ticker data (state) is stored in a thread-specific data structure called tsd in jemalloc parlance. Ticks are triggered when extents are allocated and deallocated. Once every 1000 ticks, jemalloc attempts to release some of the dirty pages hanging around (if any). This allows memory use to be kept in check over time.
This dirty page cleanup mechanism has a quirk. If the first
allocator-related action for a given thread is a free()
, a
minimally-initialized tsd is set up which does not include ticker data.
When that thread subsequently calls *alloc()
, the tsd transitions to
its nominal state, but due to a certain flag being set during minimal
tsd initialization, ticker data remains unallocated. This prevents
decay-based dirty page purging from working, effectively enabling memory
exhaustion over time. This problem has been reported upstream and
was subsequently confirmed by jemalloc developers.
The quirk described above has been addressed (by moving ticker state to a different structure) in jemalloc's development branch, but not in any numbered jemalloc version released to date (the latest one being 5.2.1 as of this writing).
This problem affects:
-
BIND 9.18+ builds with jemalloc explicitly linked in,
-
BIND 9.16 builds on FreeBSD, where jemalloc is the default system allocator.