Skip to content

Fix incorrect errno short names on FreeBSD/macOS in bwf::Errno#13240

Open
bryancall wants to merge 4 commits into
apache:masterfrom
bryancall:fix-errno-name-table
Open

Fix incorrect errno short names on FreeBSD/macOS in bwf::Errno#13240
bryancall wants to merge 4 commits into
apache:masterfrom
bryancall:fix-errno-name-table

Conversation

@bryancall

Copy link
Copy Markdown
Contributor

Problem

Reported in #13203. On FreeBSD (and macOS) Traffic Server logs connection
failures with a misleading errno name, e.g.:

CONNECT: attempt fail [CONNECTION_ERROR] to 72.167.35.147:443 for host='docs.trafficserver.apache.org' connection_result=ENOSTR [60] error=ENOSTR [60] retry_attempts=0 url='...'

ENOSTR ("Not a STREAM", an XSI STREAMS error) has nothing to do with the
actual failure, which made these logs confusing to diagnose. The numeric value
[60] is correct; only the symbolic name is wrong.

Root cause

swoc::bwf::Errno's short name used a single, hardcoded, Linux-numbered table
indexed directly by the raw errno value:

static const std::array<std::string_view, 134> ERRNO_SHORT_NAME = { "SUCCESS", "EPERM", ... };
auto errno_short_name = [](unsigned n) { return ERRNO_RANGE.contains(n) ? ERRNO_SHORT_NAME[n] : "Unknown"sv; };

errno numbering differs across platforms. Value 60 is ENOSTR on Linux but
ETIMEDOUT on FreeBSD/macOS (and ENOSTR is not defined at all on FreeBSD).
So a genuine connection timeout (ETIMEDOUT, errno 60) was printed as
ENOSTR. The numbering starts diverging at errno 11 and disagrees on roughly
70 of the values shared between Linux and the BSD-derived platforms, so this
was not a one-off.

Fix

Replace the single table with a per-platform table, each generated from that
platform's own <errno.h>, still looked up by O(1) direct index:

  • #if defined(__linux__) / #elif defined(__APPLE__) / #elif defined(__FreeBSD__).
  • Gaps in the numbering are empty entries that fall through to "Unknown".
  • An unsupported platform is a hard #error rather than silently wrong names.
  • The std::error_code formatter that shared the old table now routes through
    the same function.

The long form ({::l}) was already correct because it uses strerror(); this
only affects the symbolic short name. (Also drops a stray trailing space in the
old "E2BIG " entry.)

Testing

Compiled and verified on Linux, macOS, and FreeBSD 14.3. bwf::Errno(60) now
prints:

Platform before after
Linux ENOSTR ENOSTR (unchanged; 60 really is ENOSTR there)
FreeBSD / macOS ENOSTR ETIMEDOUT

Reproduced the original report on FreeBSD 14.3 against the 10.1.0 release: a
connection that timed out and logged connection_result=ENOSTR [60] now
reports ETIMEDOUT [60].

Fixes #13203

The errno short-name lookup indexed a single hardcoded Linux-numbered
table by the raw errno value, so on platforms with different numbering
it printed the wrong name. A connect timeout (ETIMEDOUT=60) was logged
as "ENOSTR" on FreeBSD/macOS, since 60 is ENOSTR only on Linux.

Replace the single table with a per-platform table generated from each
OS's own <errno.h>, keeping the O(1) direct index. Gaps fall through to
"Unknown" and an unsupported platform is a compile error.

Fixes: apache#13203
Copilot AI review requested due to automatic review settings June 4, 2026 20:31

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.

Pull request overview

This PR fixes swoc::bwf’s short-form errno formatting so that the symbolic name matches the platform’s actual <errno.h> numbering (not Linux’s numbering), addressing misleading log output on FreeBSD/macOS (e.g., ETIMEDOUT incorrectly printed as ENOSTR).

Changes:

  • Replaces the single Linux-numbered errno name table with per-platform tables for Linux, macOS, and FreeBSD.
  • Adds an errno_short_name(int) helper used by both bwf::Errno and the std::error_code formatter.
  • Preserves long-form errno formatting via strerror() while correcting short-form symbolic names.

Comment thread lib/swoc/src/bw_format.cc Outdated
Comment thread lib/swoc/src/bw_format.cc Outdated
The FreeBSD table was missing EPERM (errno 1), so it formatted as
"Unknown". Linux and FreeBSD also picked the ENOTSUP alias over the
more common EOPNOTSUPP for that value, which changed existing log
output. Prefer the canonical name (EAGAIN/EDEADLK/EOPNOTSUPP) and fill
in EPERM.

Add a test_bw_format case asserting bwf::Errno prints the platform's
own symbolic name for EPERM, ETIMEDOUT, and ECONNREFUSED, guarding
against the mislabel this PR fixes.
masaori335
masaori335 previously approved these changes Jun 4, 2026

@masaori335 masaori335 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.

Having the list per supported platform makes sense to keep it O(1) at lookup.

EL2HLT (Linux 51) and ENOATTR (FreeBSD 87, macOS 93) were left as
gaps in the per-platform tables and formatted as "Unknown" even
though each is defined in that platform's <errno.h>. Verified the
tables by compiling and running against the real headers on Linux,
macOS, and FreeBSD 14.3.

Restore the std::array the table was before this PR; the raw C array
was an unintended downgrade, and size() replaces the sizeof divide in
the bounds check. Add a std::error_code formatter test next to the
existing bwf::Errno cases, since that path was changed too.
Copilot AI review requested due to automatic review settings June 9, 2026 04:32

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

The prior guard asserted ECONNREFUSED, which was never one of the
missing entries, so it stayed green even against the broken tables.
Add direct ENOATTR (macOS/FreeBSD) and EL2HLT (Linux) assertions,
each #ifdef-guarded to its platform, so the suite goes red if those
gaps return. Confirmed ENOATTR fails on the pre-fix tables and
ENOATTR is undefined on Linux, so the guard is skipped there.

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@bryancall bryancall requested a review from masaori335 June 9, 2026 04:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Incorrect error code/string (ENOSTR)

3 participants