Skip to content

Fix memory leak bug#41

Merged
mwfj merged 3 commits into
mainfrom
fix-valgrind-issue
May 25, 2026
Merged

Fix memory leak bug#41
mwfj merged 3 commits into
mainfrom
fix-valgrind-issue

Conversation

@mwfj
Copy link
Copy Markdown
Owner

@mwfj mwfj commented May 25, 2026

Summary

Removes the inline specifier from the out-of-line definition of ThreadPool::GetThreadWorkerNum() in thread_pool/src/threadpool.cc so the linker has an externally-visible definition to bind to from other translation units. Unblocks the weekly Valgrind CI build, which has been failing for at least three consecutive weeks (runs 25625309388 / 25987277977 / 26357808039 on 2026-05-10, 05-17, 05-24).

Problem

weekly-valgrind.yml fails at the Build step (before valgrind runs) with:

  server/net_server.cc:122 ... undefined reference to `ThreadPool::GetThreadWorkerNum()'
  server/net_server.cc:123, :402, :487, :514 ... (same)
  include/net_server.h:163 ... (more undefined references follow)
  collect2: error: ld returned 1 exit status
  make: *** [Makefile:225: test_runner] Error 1

Root cause

The function is declared in the public header but defined as inline in a .cc file:

  • thread_pool/include/threadpool.h:68 — int GetThreadWorkerNum(); (declaration only)
  • thread_pool/src/threadpool.cc:43 — inline int ThreadPool::GetThreadWorkerNum() { return thread_nums; }

This violates the C++ ODR for inline functions: an inline function must have its definition visible in every translation unit that calls it. With the body confined to threadpool.cc:

  1. Only threadpool.cc itself can satisfy the inline call (its own internal callers at lines 79/88/90 inline fine).
  2. Other TUs (net_server.cc) see only the declaration and emit external symbol references.
  3. The inline keyword on the .cc definition tells GCC not to emit an externally-visible out-of-line copy.
  4. The linker has nothing to bind the external references to.

Why ci.yml masks it: the default -O2 build path produces a symbol layout that links anyway. The Valgrind workflow builds with -O1 -g -fno-omit-frame-pointer (required for accurate stacks), and at -O1 GCC's emission policy for inline in-.cc functions diverges, leaving the external references unresolved.

Test plan

  • make clean && make -jN CXXFLAGS_EXTRA="-O1 -g -fno-omit-frame-pointer" CFLAGS_EXTRA="-O1 -g -fno-omit-frame-pointer" NGHTTP2_CFLAGS_EXTRA="-O1 -g
    -fno-omit-frame-pointer" — clean build, no link errors; produces test_runner + server_runner
  • ./test_runner basic — 6/6 pass
  • Next scheduled weekly-valgrind.yml run completes the Build step and proceeds into the Valgrind sweep
  • Default ci.yml matrix (gcc / clang / ASan+UBSan / TSan-heavy / TSan-rest / macOS) still passes — no behavior change at -O2

Risk

Minimal. The function is a trivial one-line int accessor with no callers taking its address. Behavior is identical at every optimization level; only the symbol's linkage attribute changes.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request removes the inline specifier from GetThreadWorkerNum in threadpool.cc to prevent potential linker errors. Reviewers suggested also removing the inline specifier from SetThreadWorkerNum to avoid similar ODR violations, marking the getter as const for better correctness, and addressing a potential data race on the thread_nums variable by using std::atomic.

Comment thread thread_pool/src/threadpool.cc Outdated
Comment thread thread_pool/src/threadpool.cc Outdated
Comment thread thread_pool/src/threadpool.cc Outdated
@mwfj mwfj merged commit 98ae7d6 into main May 25, 2026
6 checks passed
@mwfj mwfj deleted the fix-valgrind-issue branch May 25, 2026 15:34
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.

1 participant