Skip to content

Give idCmdArgs a copy constructor so queued startup commands survive - #197

Open
akacross wants to merge 1 commit into
themuffinator:mainfrom
akacross:fix/cmdargs-copy-constructor
Open

akacross wants to merge 1 commit into
themuffinator:mainfrom
akacross:fix/cmdargs-copy-constructor

Conversation

@akacross

Copy link
Copy Markdown
Contributor

Fixes the dedicated-server smoke timeouts and most of the renderer startup-matrix failures that every PR and main currently show in CI. Both are one regression from f15a41f.

Cause

idCmdArgs::argv points into the object's own tokenized buffer, and idCmdArgs::operator= re-points it. f15a41f made idList::Append copy its argument into a temporary before growing the list (const type value = obj;), but idCmdArgs has no copy constructor. The implicit member-wise copy leaves value.argv aimed at the caller's buffer, and list[num] = value then computes each offset as value.argv[i] - value.tokenized, from two unrelated buffers.

Startup + commands are queued in idCmdSystemLocal::tokenizedCmds, an idList<idCmdArgs> that grows every 16 entries. So the 17th, 33rd, ... startup command reaches ExecuteTokenizedString with an empty argv[0] and is skipped silently. The same commit stopped reporting empty commands as unknown.

What it broke in CI

  • Dedicated-server smokes (Linux, macOS, Windows): +quit is the 17th command, so the server runs until the 45 s timeout ("missing marker: Game Shutdown"). On main the step only looks green because earlier failures skip it.
  • Renderer startup matrix: the self-tests that land on a growth never run ("RendererRenderGraphResource / RendererModernVisibility self-test passed", the Vulkan render-target/MRT/resolve set).
  • Outside CI, any client command line with more than 16 + commands, +set included, loses one, e.g. a +map after many +sets.

Fix

idCmdArgs( const idCmdArgs &args ) { argc = 0; *this = args; }, so every copy re-points argv.

Verification (Linux x64, GCC 16)

Check main this branch
tools/tests/linux_dedicated_server_smoke.py fail: 45 s timeout, no Game Shutdown pass, 1.1 s
renderer_validation_matrix.py --cases renderer-foundation-selftests (CI arguments) fail: RenderGraphResource and ModernVisibility missing pass
renderer_validation_matrix.py --cases renderer-vk-clear-startup fail: 9 Vulkan self-test markers missing those 9 present*
client with +quit as the 17th + command still running at 60 s exits in 4 s

*Locally it still misses only "Vulkan: validation enabled", because this machine has no Khronos validation layer installed. CI did not list that marker as missing.

New tools/tests/cmd_args_copy.py (wired into both workflows and openq4_validate.py) compiles the production idCmdArgs header, operator= and AppendArg against the real idList, copy-constructs a command and queues 40 through several growths. It fails on main and passes here.

Remaining CI failures this doesn't address

  • Windows ARM64: openq4-imported-game-regressions fails in mp_match_authentication_contract, mp_match_pause_contract and mp_match_teams_contract. They pass on Linux and Windows x64. Their logs (game-regression-logs/) aren't uploaded, so I couldn't see why. The contracts' compiler probe asks vswhere for the x64 MSVC toolset, which is a plausible ARM64 difference.
  • Linux x64 ASan+UBSan: the sanitizer build alone takes about 82 of the 90 minutes, so tests are cut off. It needs a longer timeout or a compiler cache.
  • macOS Intel and Windows ARM64 timeouts: the profile's roughly 300 sequential Python checks run past 90 minutes. Run independent validation checks in parallel #191 runs them in parallel.

🤖 Generated with Claude Code

idCmdArgs::argv points into the object's own tokenized buffer, which
operator= re-points. Since f15a41f, idList::Append copies its argument
into a temporary before growing the list, and idCmdArgs had no copy
constructor: the implicit member-wise copy left argv aimed at the
caller's buffer, and operator= then computed each argument's offset from
two unrelated buffers. The startup queue is an idList<idCmdArgs> growing
every 16 entries, so the 17th, 33rd, ... "+" command lost its text and
was silently skipped.

In CI that left the dedicated-server smokes waiting for a "+quit" that
never ran (Linux, macOS and Windows), dropped renderer self-tests from
the startup matrix (RenderGraphResource, ModernVisibility and the Vulkan
render-target set), and long client command lines lost commands such as
"+map".

The copy constructor now goes through operator=. cmd_args_copy.py
compiles the production idCmdArgs and idList, copies a command and queues
40 through several growths, and checks each one reads back intact; it
fails without this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@themuffinator themuffinator added bug Something isn't working priority: P1 Functional or qualification gap in intended scope; no release-date promise. status: blocked by CI Required validation is incomplete or failing; inspect linked run evidence. labels Oct 21, 2026 — with ChatGPT Codex Connector

@themuffinator themuffinator left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The copy constructor correctly reuses the existing rebasing assignment operator. Independently compiled the production header/operator=/AppendArg with the real idList on Windows: cbe967f loses queued and drained commands 17 and 33; this head preserves all 40 commands and passes the direct-copy case. cmd_args_copy.py also passes locally.

The successful Windows x64, Linux Clang/ARM64 and macOS ARM64 checks support the fix. Remaining timeouts are not passes. The cross-build failure was in Ubuntu package installation before compilation (liblzma5:arm64 dependency resolution); I have retried that job once. I am preparing joint validation with #191 and CI diagnostics so the command-queue fix and reduced validation time can be qualified together before integration.

Copy link
Copy Markdown
Owner

Joint validation with #191 is now running in draft integration PR #200. It preserves both original commit histories and adds Windows ARM64 native failure diagnostics plus time for sanitizer tests after the build. The independent Windows native negative control reproduces the lost 17th/33rd commands on main and passes on this head. The standalone ARM64 cross-build retry has also progressed past the earlier package-install failure.

Copy link
Copy Markdown
Owner

The targeted Linux ARM64 cross-build retry completed successfully, including ELF verification and staged-package validation: run 39460306900. The original apt dependency failure did not recur. The integrated #200 cross build also passed. Other platform/CI gates remain outstanding; this does not turn the previous timeouts or Windows ARM64 native failures into passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: P1 Functional or qualification gap in intended scope; no release-date promise. status: blocked by CI Required validation is incomplete or failing; inspect linked run evidence.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants