GPU command-queue deadlock in IOGPUFamily (Apple M5 Max, macOS 26.6.2)

[Forever Beta 1.60.1.69913] Mac freeze on entering world: GPU command-queue deadlock in IOGPUFamily (Apple M5 Max, macOS 26.6.2)

This is a widely reported Mac issue, not an isolated one. Existing threads:

The value this report adds over the existing threads is the kernel-side stack — none of
them identify where the freeze actually occurs.

Summary: On an Apple M5 Max Mac, the Classic Beta client deadlocks every time it loads
into the world. The main thread blocks forever in -[_MTLCommandBuffer waitUntilCompleted]
while Metal’s command-queue thread is stuck inside the kernel’s IOGPUFamily driver. The
client never recovers and cannot be killed normally — kill -9 leaves it unkillable in state
E, requiring a reboot. In two cases the wedged GPU queue starved WindowServer until the OS
watchdog killed it, once as a full kernel panic.

Retail WoW runs perfectly on the same machine, GPU, OS and display. This appears to be
specific to the Forever beta client. Many other Mac users report the same freeze across M1,
M2, M4 and M5 hardware.


Severity

Blocking: the beta is unplayable on this hardware — the world can never be entered. It also
takes down the desktop session, which is worse than a client crash.

Environment

Client World of Warcraft Beta ARM64 1.60.1.69893 and 1.60.1.69913 (both affected)
Machine Mac17,6, Apple M5 Max, 18 cores, 48 GB
OS macOS 26.6.2 (25G83), Darwin 25.6.0, arm64
GPU driver AGXMetalG17X 353.14, IOGPU 130.16.4, Metal 373.7, driver dated 01-Aug-2026
Displays Reproduces on Studio Display (2560x1440 @60Hz) alone, on the built-in panel (2056x1329 @120Hz) alone, and on both together
Working control Retail 12.1.0.69814 on the same machine: no problems

Reproduction

  1. Launch the Classic Beta client.
  2. Log in and reach character select — always fine.
  3. Select a character and enter the world.
  4. Loading screen appears, music plays, then the client hangs permanently.

Frequency: 6 out of 6 attempts, across two builds, two reboots and multiple configs.

The deadlock

Sampled with sample(1) while wedged. Five samples, every one showing the same two threads
with zero variation across all samples in each run:

main thread
    (World of Warcraft render path)
    -[_MTLCommandBuffer waitUntilCompleted]  (in Metal) + 76
      _pthread_cond_wait
        __psynch_cvwait

DispatchQueue "com.Metal.CommandQueueDispatch"
    -[_MTLCommandQueue _submitAvailableCommandBuffers]  + 512
      -[IOGPUMetalCommandQueue submitCommandBuffers:count:]   (in IOGPU)
        -[IOGPUMetalCommandQueue _submitCommandBuffers:count:] + 360
          IOGPUCommandQueueSubmitCommandBuffers   (in IOGPU)

The main thread waits for a command buffer to complete; the queue thread that would submit it
is blocked in the kernel submit call. Neither can advance.

A macOS WindowServer watchdog stackshot captured the kernel side of the same submit:

World of Warcraft (Wow) [1847]   main thread last ran 36.263s ago
  com.Metal.CommandQueueDispatch → Metal → IOGPU → IOKit → kernel:
    IOGPUFamily +35836 → +236660 → +237376 → +248448 → +240636 → +238872

Corroborating: CPU time advances ~1% while wedged, process state U (uninterruptible), and
gx.log / Connection.log / AsyncFile.log all stop dead at the moment of the hang. No GPU
fault or driver reset is logged — the GPU does not crash, the submit simply never returns.

In gx.log the hang always follows a Render Settings Changed line, i.e. the render-target
reconfiguration on entering the world.

The client does not recognise this GPU

Adapter 0: "Apple M5 Max" 0GB family:Unknown type:Integrated driver_ver:0.0.0.0
GpuInfo: sm:mtl_1_1, rt:None, vrs:0, bary:0, mesh:0 pull:1
Choosing low power gpu: "Apple M5 Max"

family:Unknown, 0GB VRAM reported, and a fallback to the mtl_1_1 shader family with
raytracing, VRS and mesh shaders all reported unavailable. Retail reports the same
family:Unknown, so this may not be causal — but combined with a beta-only deadlock it seems
worth checking whether an unrecognised GPU family selects an untested submission path.

Difference from the working Retail client

Same machine, same GPU, same OS, same display, one day apart:

gx.log Retail 12.1.0.69814 (works) Classic Beta (deadlocks)
Disabled Settings None LOW_LATENCY_CBS
GxLowLatencyMode BuiltIn None
World render Size: 5120x2880 (native) Size: 1x1(4916x2764 @ 50.0%)

The beta disables low-latency callbacks by default on hardware where retail enables them.
Per the client’s own CVar help, with them off a GPU→CPU readback “always takes the max GPU
frame latency” — a blocking wait on a command buffer, which is where the main thread is stuck.
Forcing GxCompatLowLatencyCallbacks "1" produced Disabled Settings: None but did not fix
the deadlock
, so this is a lead rather than the answer.

Also note the beta’s Size: 1x1(...) on the first render-settings change; retail never reports
a 1x1 drawable.

Already ruled out — please don’t spend time here

Each tested on a clean boot, one change at a time, and each reproduced the identical stack:

Tested Result
Secondary lighting: graphicsLightMode 0, raidGraphicsLightMode 0, maxLightCount 16 No effect (this is the common forum advice)
gxMTDisable 1 — all render multithreading off No effect; honoured by the client
GxMaxFrameLatency (client clamps to min 2) No effect
All seven GxCompat* = 0 (`Disabled Settings: OPT_FEATURES COPY_QUEUE
RenderScale 1 (native, no upscale) + GxMaximize 1 No effect
GxCompatLowLatencyCallbacks 1 No effect
Single display vs. dual, 60 Hz vs. 120 Hz No effect
Graphics quality settings generally Irrelevant — the wedge is below the client’s own code

Secondary issue (separate, non-fatal)

Every launch also throws a background-downloader assert:

ASSERTSAFES(locality != CAS_LOCALITY_ERROR, ...)
Unable to determine locality for BGDL. FileData ID 8470130
  with CAS error not found CKey[96E3737F73428445F73E8EF79B94E7FC]
AsyncFileThread.cpp(568)   ERROR #135

with matching CDN misses in Tact.log:
Unable to lookup file with path '0001F3F600000014:...96E3737F...'. Error(6): not found.

Survivable, and unrelated to the hang — it fires on Net Queue 0 — but it looks like a
publishing gap where the manifest references a file the CDN does not serve.

Attachments

  • 5 × sample(1) stack dumps of the wedged client (builds 69893 and 69913)
  • 1 × WindowServer userspace_watchdog_timeout stackshot showing the kernel-side IOGPUFamily block
  • 2 × kernel panic logs (one WindowServer watchdog timeout, one Halt/Restart timeout)
  • gx.log, Config.wtf, and the full client error report from a hung session
  • The same logs from the working Retail client for comparison

Happy to run any diagnostic build or CVar combination on request — the failure is 100%
reproducible and takes about two minutes to trigger.

1 Like