fix: avoid 15-byte command_name truncation in read_command_name() by Asthenia0412 · Pull Request #3607 · apache/brpc · GitHub
Skip to content

fix: avoid 15-byte command_name truncation in read_command_name() - #3607

Open
Asthenia0412 wants to merge 1 commit into
apache:masterfrom
Asthenia0412:fix/command-name-truncation
Open

Asthenia0412 wants to merge 1 commit into
apache:masterfrom
Asthenia0412:fix/command-name-truncation

Conversation

@Asthenia0412

Copy link
Copy Markdown

Background

brpc builtin command system silently truncates command names longer than 15 characters, because bvar::read_command_name() reads from /proc/self/stat whose comm field is kernel-limited to TASK_COMM_LEN = 16 bytes (15 chars + null).

Problem

Hardcoded kernel-level 15-char limit on process name makes RPC debugging difficult when users define descriptive command names (e.g. long service names).

Root Cause

The old implementation parsed /proc/self/stat:

std::ifstream fin("/proc/self/stat");
fin >> pid >> command_name;

Linux kernel's TASK_COMM_LEN = 16 means the comm field is always truncated to 15 characters.

Solution

Switch to reading from /proc/self/cmdline via the existing butil::ReadCommandLine() helper, which returns the full argv[0]. This helper is already used elsewhere in brpc (GetProgramName, pprof_service), so no new dependencies are introduced.

Verification

  • g++ -std=c++17 -fsyntax-only passes with no errors.
  • Quick runtime test confirmed:
    • /proc/self/stat comm truncates myhelloworldprocess_test_long to myhelloworldpro (15 chars)
    • /proc/self/cmdline returns full argv[0] without truncation

Fixes #1251

read_command_name() in bvar/variable.cpp was reading the command name
from /proc/self/stat's comm field, which is limited by the kernel's
TASK_COMM_LEN (16 bytes including null terminator), causing silent
truncation for any process name longer than 15 characters.

This fix switches to reading from /proc/self/cmdline via the existing
butil::ReadCommandLine() helper, which returns the full argv[0] and is
already used by other parts of brpc (GetProgramName, pprof_service).

Fixes apache#1251
@wwbmmm
wwbmmm requested a balanced review from Copilot October 14, 2026 13:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

3 open findings
What changed in this PR

Updates bvar::read_command_name() to avoid the Linux kernel TASK_COMM_LEN (15-char) truncation by switching from /proc/self/stat to /proc/self/cmdline, enabling longer command names to be captured for debugging/visibility.

Changes:

  • Replace /proc/self/stat parsing with butil::ReadCommandLine() (reads /proc/self/cmdline).
  • Add the required butil/process_util.h include and remove <fstream> usage.
  • Simplify normalization by directly underscoring the read command-line content.
File Description
src/​bvar/​variable.cpp Switches command name source to /proc/self/cmdline to avoid the 15-char truncation from /proc/self/stat.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/bvar/variable.cpp
Comment on lines +695 to +701
char cmdline[1024];
const ssize_t nr = butil::ReadCommandLine(cmdline, sizeof(cmdline), false);
if (nr <= 0) {
return std::string();
}
int pid = 0;
std::string command_name;
fin >> pid >> command_name;
if (!fin.good()) {
return std::string();
}
// Although the man page says the command name is in parenthesis, for
// safety we normalize the name.
std::string s;
if (command_name.size() >= 2UL && command_name[0] == '(' &&
butil::back_char(command_name) == ')') {
// remove parenthesis.
to_underscored_name(&s,
butil::StringPiece(command_name.data() + 1,
command_name.size() - 2UL));
} else {
to_underscored_name(&s, command_name);
}
to_underscored_name(&s, butil::StringPiece(cmdline, nr));
Comment thread src/bvar/variable.cpp
Comment on lines +695 to +696
char cmdline[1024];
const ssize_t nr = butil::ReadCommandLine(cmdline, sizeof(cmdline), false);
Comment thread src/bvar/variable.cpp
} else {
to_underscored_name(&s, command_name);
}
to_underscored_name(&s, butil::StringPiece(cmdline, nr));

@wwbmmm wwbmmm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[replied by brpc-oncall robot] Switching from /proc/self/stat to /proc/self/cmdline is the right direction to avoid the 15-char TASK_COMM_LEN truncation, but the name derived from argv[0] changes semantics and needs normalization. Note: two of the Copilot findings are false positives — (1) with_args=false already stops at the first '\0' inside butil::ReadCommandLine, so no NUL separators or arguments can leak into StringPiece; (2) the 1024-byte buffer cannot silently truncate, since ReadCommandLine returns -1 (and logs an error) when the buffer is not big enough, which this code maps to an empty name.

Comment thread src/bvar/variable.cpp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[replied by brpc-oncall robot] Beyond the path leak Copilot mentioned, this is a user-visible naming/compatibility change. comm used to be a short executable name, while argv[0] is whatever was used to launch the process; deployments that start with an absolute or relative path will now produce names like _usr_local_bin_myservice (to_underscored_name turns the leading '/' into '' and '/' into ''). That propagates to bvar_dump_file/bvar_dump_prefix/mbvar_* (monitor/bvar.<app>.data, <app> prefix) and to the default rpc_dump_dir (./rpc_data/rpc_dump/<app>), so existing monitoring/dump paths and downstream consumers (e.g. noah) change after upgrade, and the leading '_' is an additional oddity. Suggest normalizing to the basename of argv[0] (strip everything up to the last '/') before calling to_underscored_name, which still fixes the 15-char truncation while keeping the previous naming behavior.

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.

command_name大于15个字符的时候会被截断

3 participants