Skip to content

fix(get-assets): survive two macOS steamcmd papercuts (running client + Gatekeeper quarantine)#6

Open
masterrr wants to merge 2 commits into
ammaarreshi:mainfrom
masterrr:fix/get-assets-steam-running-guard
Open

fix(get-assets): survive two macOS steamcmd papercuts (running client + Gatekeeper quarantine)#6
masterrr wants to merge 2 commits into
ammaarreshi:mainfrom
masterrr:fix/get-assets-steam-running-guard

Conversation

@masterrr

@masterrr masterrr commented Jul 6, 2026

Copy link
Copy Markdown

On a fresh macOS setup, scripts/get-assets.sh can stall or die before it ever reaches the Steam login, for two unrelated reasons. Both present as a confusing hang/dialog rather than a clear error, so it's easy to assume the script or your Steam account is broken when neither is. This PR makes the script detect and handle both up front.

Encountered on:

macOS 26.2 (build 25C56)
Arch arm64 (Apple Silicon)
steamcmd Homebrew cask, build 1782532820

1. A running Steam desktop client → silent forever-hang

steamcmd and the Steam desktop client share one data directory (~/Library/Application Support/Steam on macOS, ~/.steam on Linux). When the desktop client is running it holds a single-instance lock, so steamcmd stalls forever immediately after printing:

[  0%] Checking for available updates...
[----] Verifying installation...

No error, no timeout — just a silent hang that's indistinguishable from a slow self-update. Ctrl-C leaves steamcmd in an "unclean shutdown" state, so the next run re-verifies and hangs at the same spot again — an easy loop to get stuck in.

The tell is that the self-update actually completes — the stall is after it, waiting on the lock held by the desktop client:

~/Library/Application Support/Steam/logs/bootstrap_log.txt — verification finishes, then nothing
[..] Checking for available updates...
[..] Download skipped: /steam_cmd_osx version 1782532820, installed 1782532820
[..] Nothing to do
[..] Verifying installation...
[..] Verifying all executable checksums
[..] Verification complete
[..] Not updating bootstrapper: Could not get version from file .../SteamMacBootstrapper.version
      ← hangs here: handoff to the client session, which blocks on the desktop client's lock
Meanwhile the desktop client is very much alive (~12 processes holding the dir)
steam_osx
ipcserver
Steam Helper  (×9)

Confirmed by pgrep -fl 'Steam.AppBundle'. The client's own console_log.txt even showed it opening the Generals Zero Hour store page seconds earlier — it was actively in use.

Fix: a preflight check that detects a running Steam client (steam_osx / Steam.AppBundle on macOS, steam on Linux) and exits with an actionable message instead of hanging:

Error: the Steam desktop client is running.
steamcmd shares Steam's data directory, and the running client locks it —
steamcmd would hang forever after "Verifying installation...".
Quit Steam completely (Steam > Quit Steam, or Cmd-Q on macOS), then re-run this script.

2. Gatekeeper quarantine → blocking "cannot verify" dialog

Homebrew installs the steamcmd cask with com.apple.quarantine set across its entire tree. steamcmd bundles unnotarized frameworks — notably Breakpad.framework (its crash reporter) — so on first run macOS pops a blocking modal that stops steamcmd before it can log in:

"Breakpad.framework" Not Opened
Apple could not verify "Breakpad.framework" is free of malware that may harm your Mac or compromise your privacy.
[ Done ] [ Move to Bin ]

(The only buttons are Done and Move to Bin — no "Open Anyway" — so there's no in-dialog way past it.)

xattr — the quarantine flag is on the whole install, not just one file
$ find "$(brew --prefix)/Caskroom/steamcmd" -exec xattr -p com.apple.quarantine {} \; -print
0381;...;;...  .../Caskroom/steamcmd/1782532820
0381;...;;...  .../MacOS/Frameworks/Breakpad.framework
0381;...;;...  .../MacOS/Frameworks/Breakpad.framework/Versions/A/...
   ... (every file in the tree)

Clearing it with xattr -dr com.apple.quarantine on the cask root drops the count to 0 and the dialog never reappears.

Fix: strip the quarantine flag off the steamcmd Caskroom install before invoking it — guarded to macOS + Homebrew, and a no-op if the cask isn't present:

if [[ "$(uname)" == "Darwin" ]] && command -v brew >/dev/null 2>&1; then
    STEAMCMD_CASK="$(brew --prefix)/Caskroom/steamcmd"
    [[ -d "$STEAMCMD_CASK" ]] && xattr -dr com.apple.quarantine "$STEAMCMD_CASK" 2>/dev/null || true
fi

Why in the script (vs. the README)

Both are environmental, not bugs in the fetch logic — but they hit at exactly the moment a new user runs this script for the first time, and both fail silently (a hang and a modal, not a message on stdout). Handling them here turns two "why is this broken?" dead-ends into either an automatic fix (quarantine) or a one-line instruction (quit Steam). The README's brew install --cask steamcmdget-assets.sh flow now just works on a clean macOS box.

Safety / cross-platform

  • Both checks are no-ops when they don't apply — nothing changes when Steam isn't running and no quarantine is set; the script proceeds exactly as before.
  • pgrep / xattr / brew are all present on the target platforms; brew --prefix resolves both Apple Silicon (/opt/homebrew) and Intel (/usr/local).
  • The quarantine strip is macOS-only (uname == Darwin) and touches only the steamcmd cask directory.
  • Verified with bash -n on the final script; confirmed the running-client guard passes with Steam quit and fires on a live match, and that the quarantine path resolves to the real Caskroom install and clears to 0 flagged files.

Commits

  1. fix(get-assets): fail fast when the Steam desktop client is running
  2. fix(get-assets): clear macOS Gatekeeper quarantine on steamcmd up front

🤖 Generated with Claude Code

masterrr and others added 2 commits July 6, 2026 12:02
steamcmd and the Steam desktop client share one data directory
(~/Library/Application Support/Steam on macOS, ~/.steam on Linux). When the
desktop client is running it holds a single-instance lock, so steamcmd stalls
forever right after printing "Verifying installation..." — no error, just a
silent hang that's easy to mistake for a slow self-update.

Add a preflight check that detects a running Steam client and exits with an
actionable message ("Quit Steam completely, then re-run") instead of hanging.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Homebrew installs the steamcmd cask with the com.apple.quarantine flag set on
its whole tree. steamcmd bundles unnotarized frameworks (e.g.
Breakpad.framework), so on first run Gatekeeper pops a blocking "Apple could
not verify ... malware" dialog that stops steamcmd before it can log in.

Strip the quarantine flag off the steamcmd Caskroom install before invoking it,
guarded to macOS + Homebrew and a no-op if the cask isn't present. Turns a
manual "run xattr -dr yourself" step into something the script handles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@masterrr masterrr changed the title fix(get-assets): fail fast when the Steam desktop client is running fix(get-assets): survive two macOS steamcmd papercuts (running client + Gatekeeper quarantine) Jul 6, 2026
MYSOREZ referenced this pull request in MYSOREZ/GeneralsZH-Android-Port Jul 7, 2026
…amespySDK

Run #6 (first run to reach the engine compile; ninja -k 0 surfaced the
complete error set) had exactly two root causes behind 165 errors:

1. 164x "windows_base.h file not found": CompatLib picked DXVK include
   dirs by APPLE-vs-rest, but the real split is source-build vs
   prebuilt tarball — Android builds DXVK from the same git source as
   macOS (Wine-style include/native layout), only desktop Linux uses
   the flat steamrt tarball. Branch on (APPLE OR ANDROID); same for
   skipping the tarball-only lib/ link dir.

2. GamespySDK's gsthreadlinux.c calls pthread_cancel, which bionic
   deliberately omits. It's a pinned remote FetchContent, so instead
   of forking for one line, rewrite the call to a successful no-op via
   a per-target macro on Android (same rationale as the CompatLib
   TerminateThread fix: shutdown-time last-resort kill, safe to skip).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012kbvTayV2STgXpff26tSFq
MYSOREZ referenced this pull request in MYSOREZ/GeneralsZH-Android-Port Jul 7, 2026
Run #8 was down to 3 unique errors (from 165 in run #6):

1. INI.cpp scanType<float>: the NDK's libc++ explicitly deletes
   floating-point std::from_chars, same situation as Apple SDKs —
   extend the existing __APPLE__ strtod fallback to __ANDROID__.

2. WWDownload/FTP.cpp includes <sys/timeb.h>, which bionic doesn't
   ship; nothing in the file uses it — excluded on Android.

3. The GamespySDK pthread_cancel stub never reached the compile line:
   CMake silently drops function-style macros from
   COMPILE_DEFINITIONS. Pass it as a raw compile option instead
   (verified missing in run #8's failing gscommon command).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012kbvTayV2STgXpff26tSFq
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.

1 participant