Skip to content

fix(libc): start the guest environment empty instead of copying the host's - #5772

Merged
adriadam10 merged 3 commits into
boykopovar:mainfrom
DavidSamir:fix/libc-empty-guest-environment
Oct 16, 2026
Merged

adriadam10 merged 3 commits into
boykopovar:mainfrom
DavidSamir:fix/libc-empty-guest-environment

Conversation

@DavidSamir

Copy link
Copy Markdown
Contributor

What

PS5MC (PPSA99420) exits about a second after start with XBMC_Run returned -1 (exit code -1) when the host has HOME set. The guest environment is copied from the host's, so Kodi's getenv("HOME") returns a host path (C:\Users\<name> on Windows, /home/<name> on Linux) and it builds its profile folder from it (C:\Users\<name>/.kodi), which it then cannot use. Without HOME in the host environment the title keeps running.

HOME is set on every Linux system, and on Windows by Git for Windows, MSYS2 and Cygwin shells, so this hits anyone who starts a title from them. On the console a title starts with no such variable, and libkernel's environ export is already an empty environment (#2090).

Cause. Environment() seeds the guest environment from the host CRT's _environ/environ on first use, so every host variable (HOME, PATH, USERPROFILE, TEMP and the rest) is visible to getenv.

The guest environment now starts empty. getenv, setenv, unsetenv and putenv work as before on the variables the title sets itself, and the host environment is still never changed. The runtime's own settings (APS5_TRACE_CALLS, ANYPS5_SYSTEM_FONTS and the others) are read by host code with the host getenv, so they are unaffected.

Three commits:

  1. fix(libc): start the guest environment empty instead of copying the host's: Environment.cpp, and guest_environment's first checks, which encoded the inheritance: a variable set in the host now reads as absent in the guest, and the host value is unchanged after guest setenv.
  2. test(libc): keep the host's HOME and PATH out of the guest environment: with HOME set in the host, getenv("HOME") and getenv("PATH") in the guest return null.
  3. docs(debt): record that the guest environment starts empty.

There is no fourth step to split out; the change is one function.

Tested

Windows (69715e8 on main 78f1aea, Windows 11 10.0.26300, WinLibs GCC 15.2.0 r7, Release):

  • PS5MC (PPSA99420, catalog release), 40 s each, with HOME set in the host (C:\Users\<name>), alternating: with main's libraries it exits with code -1 after 4 s and after 1 s, its last log line [kodi-ps5] heap: 2048 MiB of direct memory; with the branch's it is still running at 40 s both times. Run without HOME in the host, it keeps running with main's libraries too. The exit message XBMC_Run returned -1 and the path C:\Users\<name>/.kodi were on the stack when LibcTerminate_nid_no_patch was reached (gdb).
  • With Environment.cpp as on main and the tests kept, guest_environment aborts (exit 0xc0000409) at the first new check, a host variable visible to the guest. With the change it passes 5/5 (--repeat until-fail:5), and guest_getopt, guest_call_trace, guest_call_trace_abort, guest_font, guest_font_writing_line, guest_hostname, guest_audio_in_capture, guest_audio_in_no_device, file_streams and guest_posix_filesystem pass 3/3. These include the tests that set host variables for the runtime's own settings and getopt's POSIXLY_CORRECT, set through the guest's setenv.
  • Titles from the homebrew catalog, 35 s each with main's libraries and with the branch's, HOME set in the host, windows kept off-screen: ccleste (PPSA59322), RommPS (PPSA76677), SwanStationPS5 (PPSA98510), ProsperoTV (PPSA99003), DOOM (PPSA99666), ScreenTester5 (PPSA69420), Prospero Vibrate (PPSA99920), SymphonyStation5 (PPSA17641), ProsperoStore (PPSA99000), OpenNOW (PPSA99082), ProsperoRadio (PPSA99001) and PSXS5 (PPSA97510) are all still running at 35 s with both, with the same last kind of log line. PSXS5 logged fewer periodic statistics lines in the first pair of runs; four more alternating runs gave 82 lines with each set.
  • Probes of 122 lines over the descriptor functions, 865 over streams, 188 over the file, directory, vector and mapping functions, 431 over time, number, character and string functions and 19 others (about 3,400 lines): no line differs, apart from a log file size in the fdopen probe that changes from run to run.
  • Full ctest --parallel 4 on a full build of the last commit: 1137 of 1137 pass.
  • Each commit alone: each of the three was checked out in order, the libraries and the tests rebuilt, and guest_environment, guest_getopt and guest_hostname pass 3/3 at each. At no commit does a rebuilt library lose an exported name.
  • tools/check_conventions.py --base origin/main passes. tools/pr_overlap.py --branch reports no overlap with open pull requests.

Linux (same commit, WSL2 Ubuntu 24.04, GCC 13.3.0, Release): libs builds, and guest_environment and guest_getopt pass 3/3, so the guest no longer sees the Linux host's variables either.

Not checked on a console. Whether the console starts a title with any environment variables at all is not measured; the debt note says so.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: PPSA99420 (PS5MC)
  • AI-assisted: yes

@screamm

screamm commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Cross-check on Windows: #5772 head 69715e839 merged onto main 6239ceffc; the merge is clean.

Host: Windows 11 Pro 26220, WinLibs MinGW-w64 GCC 15.2.0 r7, Ninja, Release, NVIDIA RTX 4070 (Ryzen 7 5700X).

  • Build: full build (cmake --build build -- -k 0) and libs both succeed, with no new warnings.
  • Tests, --repeat until-fail:3: all 11 pass 3/3 (33 of 33 runs): guest_environment, guest_getopt, guest_hostname, guest_call_trace, guest_call_trace_abort, guest_font, guest_font_writing_line, guest_audio_in_capture, guest_audio_in_no_device, file_streams and guest_posix_filesystem.
  • Suite, ctest -j8 --timeout 120 -E '^agc_driver_|^video_out_flip': 808 tests. 800 pass, including the 2 skipped (agc_host_import_sparse, guest_video_out_wqhd_detection_no_vulkan). 8 time out under host load and all 8 pass when run alone: conventions_function_bodies, conventions_ci_gate, debt_split, hardware_oracle_compare, conventions_bom_shebang, guest_raise_exception, guest_none_relocations and tls_function_coverage_register_address_loads. Plain main on the same host lost 12 the same way, and all 12 pass alone.

Titles. Catalog releases, relinker --windows --registry unused-filter=0. 60 s per run, with the display on. HOME=C:\Users\<user> was set in the host for every run. All libraries come from one build: main's or the merge's.

Title main this PR
PS5MC (PPSA99420), run 1 exit 0xFFFFFFFF after 5.3 s, no frame still running at 60 s, PS5MC (Kodi 22) | FPS: 5.76 (211)
PS5MC, run 2 exit 0xFFFFFFFF after 3.2 s, no frame still running at 60 s, PS5MC (Kodi 22) | FPS: 11.89 (464)
ProsperoRadio (PPSA99001), 3 pairs running at 60 s: 622, 628, 3377 frames running at 60 s: 1477, 3245, 3369 frames
ProsperoTV (PPSA99003), 3 pairs running at 60 s: 151, 300, 680 frames running at 60 s: 256, 543, 672 frames

PS5MC on main (download0/ps5-opengl.log):

[debug:0] [kodi-ps5] HOME already set to C:\Users\<user>
[debug:0] [kodi-ps5] starting XBMC_Run
[debug:0] [kodi-ps5]   sqlite log (14): os_unix.c:44775: (2) open(/C:\Users\<user>\.kodi\userdata\Database\Addons33.db) -
[debug:0] [kodi-ps5] XBMC_Run returned -1
[debug:0] [kodi-ps5] exiting

That run also created C:\Users\<user>\.kodi on the host (userdata/guisettings.xml, profiles.xml, temp/kodi.log).

PS5MC with the PR:

[debug:0] [kodi-ps5] HOME=/data/ps5mc/kodi22
[debug:0] [kodi-ps5] starting XBMC_Run

The run continues, with no XBMC_Run returned.

Control: main with HOME removed from the host environment is still running at 60 s (PS5MC (Kodi 22) | FPS: 18.60 (873), HOME=/data/ps5mc/kodi22).

ProsperoRadio and ProsperoTV have no stop line with either build. The last lines are the periodic [RADIO] frames=600 ... and [TV] frames=600 .... Frame counts follow host load, not the PR. In the third pair the PR ran first on an idle host and the counts match: Radio 3369 vs 3377 (59.95 / 59.96 fps), TV 672 vs 680.

Verdict: confirmed. With HOME set, PS5MC exits with XBMC_Run returned -1 on main and keeps running with this PR. No regression in the tests, the suite, ProsperoRadio or ProsperoTV.

AI-assisted: yes (Claude Code)

@DavidSamir

Copy link
Copy Markdown
Contributor Author

Linux evidence for PS5MC (PPSA99420, catalog release): WSL2 Ubuntu 24.04, GCC 13.3.0, main 6239cef with and without this PR's two code files (unchanged on main since), relinked with --to-intel, HOME=/home/david as in any Linux shell, 40 s, two runs each:

  • main: it logs [kodi-ps5] HOME already set to /home/david and Kodi maps special://home/ is mapped to: /home/david/.kodi, the host user's home, which is not a guest folder. It keeps running, unlike on Windows, where the same inherited HOME makes it exit with -1.
  • This PR: the HOME already set line is gone and Kodi maps special://home/ is mapped to: /data/ps5mc/kodi22/.kodi, the title's own data folder.

Nothing was written to the host's /home/david/.kodi.

AI-assisted: yes

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 3987 docs/dev/debt/libc.md
PR 5021 docs/dev/debt/libc.md
PR 5303 docs/dev/debt/libc.md
PR 6044 core/libs/tests/GuestEnvironment.cpp
PR 6222 docs/dev/debt/libc.md

@LeandroLP23

Copy link
Copy Markdown
Contributor

The title on Windows, for the side that only had a build and tests: with this PR PS5MC reaches Kodi's home screen from a shell with HOME set.

Setup: Windows 11 Home 26300, AMD Radeon 860M (driver 32.0.13058.8001), WinLibs GCC 15.2.0, Release. Started from a Git for Windows bash, so HOME=/c/Users/leand is in the host environment. Catalog PPSA99420 1.2, relinked with --windows. main 5d9dcc42d against this head 69715e839 merged onto it (14e8dff43, clean merge). 60 s runs, no input.

Build Result
main [kodi-ps5] HOME already set to C:\Users\leand, then Kodi opens C:\Users\leand/.kodi/userdata/..., logs [kodi-ps5] exiting, and the process ends after 1 s with exit code 0xffffffff
this PR, 2 runs [kodi-ps5] /data/ps5mc/kodi22 is usable, HOME=/data/ps5mc/kodi22; alive at 60 s, 19.2 and 19.5 FPS on the window counter, closed normally

A frame dump from a third 45 s run shows Kodi 22's home screen (Estuary: main menu from TV to Weather, clock, the weather-provider prompt). The main run also left a C:\Users\<name>\.kodi folder in the host user profile, which this PR avoids as well.

Not tested: Linux (covered above by @DavidSamir), NVIDIA.

AI-assisted: yes (Claude Code)

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the diff, guest_environment (fails with Environment.cpp from main, passes with the change) and the libc/libs ctest scope; the runtime's own settings are read with the host getenv, so they are unaffected. Matches libkernel's empty environ (#2090) and the Windows/Linux runs of PS5MC reported in the thread; merging.

@adriadam10
adriadam10 merged commit d96e0e5 into boykopovar:main Oct 16, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants