Skip to content

fix: Remove race condition in memory allocator initialization#376

Open
yurekami wants to merge 1 commit intodeepseek-ai:mainfrom
yurekami:fix/memory-allocator-race-condition
Open

fix: Remove race condition in memory allocator initialization#376
yurekami wants to merge 1 commit intodeepseek-ai:mainfrom
yurekami:fix/memory-allocator-race-condition

Conversation

@yurekami
Copy link
Contributor

@yurekami yurekami commented Jan 4, 2026

Summary

Problem

The original code had a race condition in GlobalMemoryAllocator.cc:

static bool gAllocatorInited = false;  // Plain bool, not atomic

void *allocate(size_t size) {
  if (!gAllocatorInited) {  // Multiple threads can pass this check
    std::call_once(gInitOnce, loadMemoryAllocatorLib);
    gAllocatorInited = true;  // Can be reordered with gAllocator write
  }

Issues:

  1. gAllocatorInited is a plain bool, not atomic - no synchronization
  2. Instruction reordering: gAllocatorInited = true can execute before std::call_once fully completes
  3. Memory visibility: other threads may see gAllocatorInited = true while gAllocator is still uninitialized

Solution

Remove the redundant flag and rely solely on std::call_once:

void *allocate(size_t size) {
  std::call_once(gInitOnce, loadMemoryAllocatorLib);

Why this works:

  • std::call_once provides full happens-before guarantees (C++11 standard)
  • After first execution, call_once becomes a fast single atomic load (efficient fast-path)
  • No performance degradation - simpler code with same or better performance

Test plan

  • Verify existing unit tests pass
  • Code review for thread-safety correctness
  • The fix is minimal and follows the principle of relying on well-tested standard library primitives

🤖 Generated with Claude Code

Fixes deepseek-ai#315

The gAllocatorInited boolean flag had a race condition where:
- Multiple threads could see gAllocatorInited=false simultaneously
- Memory ordering issues could cause threads to see gAllocatorInited=true
  before gAllocator was fully initialized

The fix removes the redundant flag and relies solely on std::call_once,
which already provides thread-safe initialization with proper memory
ordering guarantees and an efficient fast-path after first execution.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Potential Race Condition in Memory Allocator Initialization

1 participant