From bf85cd0b669b91138fbca50e9360dced8528a11d Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Wed, 14 Oct 2026 15:22:11 -0400 Subject: [PATCH] Retry IDNA table allocation after a transient failure --- src/table_store.hpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/table_store.hpp b/src/table_store.hpp index cd1d515..ac47ad7 100644 --- a/src/table_store.hpp +++ b/src/table_store.hpp @@ -5,8 +5,9 @@ // code; compression only affects on-disk size and one-time init. // // Thread-safe without mutex: atomic CAS + spin-wait. ensure_tables() returns -// false if initialization fails (OOM, corrupt blob); callers must treat that -// as a hard error and not touch table pointers. +// false if initialization fails. A corrupt blob stays failed for the process. +// An allocation failure is not latched: a later call tries again. Callers +// must treat a false return as a hard error and not touch table pointers. #pragma once #include "raw_inflate.hpp" @@ -303,8 +304,12 @@ inline constexpr uint64_t kTablesSpinLimit = 1'000'000'000ull; std::memory_order_acquire)) { uint8_t* buffer = new (std::nothrow) uint8_t[table_blob::uncompressed_size]; if (buffer == nullptr) { - tables_init_state.store(kTablesFailed, std::memory_order_release); + // Leave the state uninitialized so a later call can retry. A corrupt + // blob (below) is permanent; running out of memory may not be. + // LCOV_EXCL_START + tables_init_state.store(kTablesUninit, std::memory_order_release); return false; + // LCOV_EXCL_STOP } const size_t n = deflate::inflate_raw(table_blob::compressed, @@ -376,9 +381,15 @@ inline constexpr uint64_t kTablesSpinLimit = 1'000'000'000ull; if (state == kTablesReady) { return true; } - if (state == kTablesFailed) { + // Failed is permanent. Uninit means the peer gave up after a failed + // allocation: do not spin, the next call can take the init slot. One + // comparison, same shape as the old Failed check, so this wait loop does + // not grow the unity translation unit. + // LCOV_EXCL_START + if (state != kTablesInProgress) { return false; } + // LCOV_EXCL_STOP #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \ defined(_M_IX86) #if defined(__GNUC__) || defined(__clang__)