Fix infinite purging loop in HPA

As reported in #2449, under certain circumstances it's possible to get
stuck in an infinite loop attempting to purge from the HPA. We now
handle this by validating the HPA settings at the end of
configuration parsing and either normalizing them or aborting depending on
if `abort_conf` is set.
This commit is contained in:
Kevin Svetlitski
2023-07-17 15:22:26 -07:00
committed by Qi Wang
parent 424dd61d57
commit 3aae792b10
6 changed files with 105 additions and 2 deletions

View File

@@ -144,6 +144,7 @@ static void default_junk_free(void *ptr, size_t usize) {
void (*JET_MUTABLE junk_alloc_callback)(void *ptr, size_t size) = &default_junk_alloc;
void (*JET_MUTABLE junk_free_callback)(void *ptr, size_t size) = &default_junk_free;
void (*JET_MUTABLE invalid_conf_abort)(void) = &abort;
bool opt_utrace = false;
bool opt_xmalloc = false;
@@ -959,7 +960,7 @@ malloc_abort_invalid_conf(void) {
assert(opt_abort_conf);
malloc_printf("<jemalloc>: Abort (abort_conf:true) on invalid conf "
"value (see above).\n");
abort();
invalid_conf_abort();
}
static void
@@ -1081,6 +1082,46 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) {
return ret;
}
static void
validate_hpa_settings(void) {
if (!hpa_supported() || !opt_hpa || opt_hpa_opts.dirty_mult == (fxp_t)-1) {
return;
}
size_t hpa_threshold = fxp_mul_frac(HUGEPAGE, opt_hpa_opts.dirty_mult) +
opt_hpa_opts.hugification_threshold;
if (hpa_threshold > HUGEPAGE) {
return;
}
had_conf_error = true;
char hpa_dirty_mult[FXP_BUF_SIZE];
char hugification_threshold[FXP_BUF_SIZE];
char normalization_message[256] = {0};
fxp_print(opt_hpa_opts.dirty_mult, hpa_dirty_mult);
fxp_print(fxp_div(FXP_INIT_INT((unsigned)
(opt_hpa_opts.hugification_threshold >> LG_PAGE)),
FXP_INIT_INT(HUGEPAGE_PAGES)), hugification_threshold);
if (!opt_abort_conf) {
char normalized_hugification_threshold[FXP_BUF_SIZE];
opt_hpa_opts.hugification_threshold +=
HUGEPAGE - hpa_threshold;
fxp_print(fxp_div(FXP_INIT_INT((unsigned)
(opt_hpa_opts.hugification_threshold >> LG_PAGE)),
FXP_INIT_INT(HUGEPAGE_PAGES)),
normalized_hugification_threshold);
malloc_snprintf(normalization_message,
sizeof(normalization_message), "<jemalloc>: Normalizing "
"HPA settings to avoid pathological behavior, setting "
"hpa_hugification_threshold_ratio: to %s.\n",
normalized_hugification_threshold);
}
malloc_printf(
"<jemalloc>: Invalid combination of options "
"hpa_hugification_threshold_ratio: %s and hpa_dirty_mult: %s. "
"These values should sum to > 1.0.\n%s", hugification_threshold,
hpa_dirty_mult, normalization_message);
}
static void
malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
bool initial_call, const char *opts_cache[MALLOC_CONF_NSOURCES],
@@ -1749,6 +1790,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
/* Re-enable diagnostic "-Wtype-limits" */
JEMALLOC_DIAGNOSTIC_POP
}
validate_hpa_settings();
if (opt_abort_conf && had_conf_error) {
malloc_abort_invalid_conf();
}