An out-of-memory abort that looked like a network hang
Installing a build on the X1 fetches about 62 MB of kernel and 57 MB of speech model over HTTP on the wire. Roughly half the time it appeared to hang: the log froze part-way through the fetch, control packets got no reply, and the machine had to be power-cycled. Because the install formats the EFI system partition before it fetches anything, a power cycle at that point leaves the internal disk unbootable. A successful fetch runs at line rate in about five seconds.
Two mechanisms were consistent with the symptom and they were distinguishable, so both were written down with the signal that would tell them apart. One was an allocation failure during buffer growth. The other was the Management Engine holding bus arbitration through a per-frame tail write, which on this part can cost up to 100 ms a time, and the driver writes that register once per frame where Linux batches it once per poll of up to 64 frames.
It was the first one, and it proved it by bricking the machine.
The failure that settled it
On 30 September the X1 was left with no boot image for half an hour. The install formatted the partition, started the fetch, and the fetch failed:
disk formatting the EFI system partition
disk fetch of pathos.elf failed: out of memory: needed a 66050128-byte
block, buffer held 0
Twice, from a different session, the same failure produced no log at all, because the lines were overwritten before they shipped. The symptom was a load command that was visibly received and then silent.
That is the worst shape a failure can have on this path. It looks exactly like a command that was ignored, and the natural response to a command that was ignored is to reboot - which is the one action that turns it into a recovery with a USB stick and somebody standing in front of the machine.
Why the memory was not there
The download was accumulated into a growing buffer, and a growing buffer doubles. A 62 MB file ends up in a 64 MB allocation, reached by asking for a fresh 64 MB block while the old 32 MB one is still held - about 96 MB briefly live, and, which is the part that matters, a single contiguous 64 MB region. The heap is a fixed 256 MiB behind a first-fit free list.
What made that block unavailable was the speech work. The models are loaded lazily and kept: base.en at around 57 MiB and the streaming model at around 60 MiB, loaded on the first press of a key, with session caches churning on top. A machine that has done any dictation has two large resident blocks that were not there at boot. The heap had free memory. It did not have 66 MiB of it in one piece.
That is also why it was intermittent, and why it got worse through a session rather than failing consistently. Fragmentation is a function of what the machine has been asked to do.
The proof was in the recovery: the same file, from the same server, failed twice on a heap forty minutes old and installed first time immediately after a reboot.
The fix
The fetch no longer buffers the file. Everything available is still drained on every pass into a bounded buffer, which is fast and keeps the receive ring empty, and the buffer is handed to the sink in 256 KiB pieces with the network polled between each one. Polling is what empties the ring and it does not require reading from the connection, so a slow write no longer starves it. If the sink cannot keep up, the TCP receive buffer fills, the window closes and the sender waits - which is backpressure, and is what should happen.
An install now costs a quarter of a megabyte whatever it is installing. A file bigger than the free memory has stopped being a different kind of problem from a file bigger than the disk.
The other half of the fix is that the panic handler now prints the panic message rather than only the word PANIC and a source line, through a path that does not itself allocate - because the panic being reported might be an allocation failure. An out-of-memory abort presenting as a silent network hang was not one bug, it was a bug plus an instrument that refused to describe it.
What is not built
The partition is still formatted before the first fetch, deliberately. A partition left over from a failed install holds a truncated kernel with a plausible directory entry, and the firmware would load it. That remains the right trade now that the fetch does not fail for want of memory, and the exposure that is left is a fetch failing for want of a network, which a retry fixes without a reboot.
The Management Engine arbitration theory was never disproved. It is instrumented and the counters are there; it simply was not what was happening this time. The per-frame tail write is still a per-frame tail write.