Skip to content

fix(logger): write stdout/stderr via utf8_str instead of wxConvLibc (#40) - #42

Merged
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/log-stdout-utf8
Jun 9, 2026
Merged

fix(logger): write stdout/stderr via utf8_str instead of wxConvLibc (#40)#42
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/log-stdout-utf8

Conversation

@got3nks

@got3nks got3nks commented Jun 9, 2026

Copy link
Copy Markdown

Summary

Fixes #40amuled -o corrupts non-ASCII log lines on stdout when the process locale isn't UTF-8 capable (common in minimal containers without LANG/LC_ALL exported). The on-disk logfile path is unaffected because it writes UTF-8 explicitly via wxConvUTF8.

@ngosang did the full root-cause analysis in the issue body — unicode2char() uses wxConvLibc (C-library locale converter), which returns NULL in a C locale, after which the fallback path collapses each non-ASCII char to ?. amuled never calls setlocale(LC_ALL, "") (only CaMuleExternalConnector does, for amulecmd / amuleweb).

Fix

Switch the stdout/stderr log sinks to wxString::utf8_str(), which always returns UTF-8 regardless of locale. The two sinks (logfile, stdout) now both write UTF-8 by construction.

Five call sites:

  • CLogger::DoLine stdout path (Logger.cpp:274) — the main reported bug
  • CLogger::EmergencyLog stderr path (Logger.cpp:288) — same pattern
  • CaMuleExternalConnector::Show() (ExternalConnector.cpp:302) — amulecmd / amuleweb interactive output. Connectors do call setlocale(LC_ALL, "") at startup, but that doesn't help in minimal containers where LANG / LC_ALL aren't exported (setlocale("") then falls back to C). Per @ngosang's follow-up comment ("Review also src/ExternalConnector.cpp, I don't trust Linux locales").
  • --version banner (ExternalConnector.cpp:532)
  • "FATAL ERROR: File does not exist" config-init message (ExternalConnector.cpp:546)

Not addressed in this PR

  • ExternalConnector.cpp:243, 382 — libreadline integration; readline expects locale-encoded bytes, not UTF-8.
  • ExternalConnector.cpp:681, 682 — version / OS-description strings cached for HTTP User-Agent. Worth a follow-up but doesn't affect the immediate user-visible bug.

Verification

Standalone wxString conversion test compiled against the same wxWidgets the build uses, with setlocale(LC_ALL, "C") to mimic amuled's runtime locale:

via wxConvLibc (unicode2char): [(null - conversion failed)]
via utf8_str():                [share: caf\xc3\xa9 / na\xc3\xafve / \xe2\x80\x9chello\xe2\x80\x9d / \xe2\x86\x92 / \xe6\x96\x87]

wxConvLibc.cWX2MB() returns NULL → runtime fallback in unicode2char() collapses to ? (exactly the symptom @ngosang reported). utf8_str() returns clean UTF-8 bytes for accented chars, smart quotes, arrow, and CJK char.

Backward compat

wxString::utf8_str() is locale-independent and produces the same UTF-8 bytes on every platform. No protocol change, no behavior change for users whose locale was already UTF-8 (they were getting UTF-8 either way — the bug was masked when setlocale("") happened to produce a UTF-8 locale).

…mule-project#40)

amuled never calls `setlocale(LC_ALL, "")`, so its C locale stays at
the default `C`. The on-disk log path writes UTF-8 explicitly via
`wxConvUTF8` in `FlushApplog` and is fine. The stdout/stderr path
goes through `unicode2char()` which uses `wxConvLibc` -- the C
library locale converter -- which collapses non-ASCII bytes to `?`
/ U+FFFD when the process locale isn't UTF-8 capable. Result: log
lines containing accented filenames, server messages, fancy
quotes, etc. come out mangled when `amuled -o` runs in a minimal
container (`LANG`/`LC_ALL` unset), while the same lines in
`~/.aMule/logfile` are perfectly UTF-8. (amule-project#40 from @ngosang with a
full root-cause analysis.)

Switch the stdout/stderr log sinks to `wxString::utf8_str()`,
which always returns UTF-8 regardless of the process locale. The
two sinks (logfile, stdout) now both write UTF-8 by construction.

Also apply the same change to the four other locale-sensitive
print sites that share the bug shape in the connectors:

  * `CaMuleExternalConnector::Show()` -- command output / prompts
    from amulecmd and amuleweb
  * `--version` banner
  * "FATAL ERROR: File does not exist" config-init message
  * `CLogger::EmergencyLog` stderr path (same pattern as DoLine)

Connectors do call `setlocale(LC_ALL, "")` at startup, so they
would work in a normal interactive shell -- but they hit the same
"C locale fallback" trap in minimal containers where `LANG` /
`LC_ALL` aren't exported. ngosang flagged this in a follow-up
comment ("Review also src/ExternalConnector.cpp, I don't trust
Linux locales").

Not addressed in this PR (separate concerns):

  * `ExternalConnector.cpp:243, 382` -- libreadline integration;
    readline expects locale-encoded bytes, not UTF-8.
  * `ExternalConnector.cpp:681, 682` -- version/OS strings cached
    for HTTP User-Agent. Should also be UTF-8 but the conversion
    is one-shot at startup so the immediate user-visible bug is
    elsewhere.

Verified on macOS with a standalone wxString test that calls
`setlocale(LC_ALL, "C")` to mimic amuled's runtime: `wxConvLibc`
returns NULL (conversion failed); `utf8_str()` returns clean UTF-8
bytes for the accented chars, smart quotes, arrow, and CJK char.
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.

amuled -o corrupts non-ASCII log lines on stdout (uses C-locale wxConvLibc, never calls setlocale); on-disk logfile is fine

1 participant