Skip to content

Toolchain download restarts from zero at ~90MB and never completes (no resume) #1370

Closed

Description

@zackees

Summary

fbuild cannot provision the ARM toolchain on Windows: the download of arm-gnu-toolchain-15.2.rel1-mingw-w64-x86_64-arm-none-eabi.zip (282 MB) restarts from zero every time it reaches roughly 80–98 MB, and never completes.

Reproduced via bash compile samd21 --examples Blink in FastLED, which drives fbuild <dir> build -e samd21.

Observed

Parsed from the progress output of a single invocation:

samples: 145 | peak MB: 98
restarts: 5
  reset 98MB -> 4MB
  reset 80MB -> 6MB
  reset 96MB -> 3MB

Roughly 450 MB transferred for zero net progress, and the run still had not produced a toolchain. Every attempt dies in the same 80–98 MB band, which reads like a timeout or a dropped connection rather than a random network fault.

Impact

Two distinct problems, and the second is the serious one:

  1. No resume. The partial file is discarded on failure. Accept-Ranges: bytes is advertised by the ARM developer host, so a ranged retry would pick up where it left off. Instead each retry pays full price.
  2. No progress across retries, so it cannot converge. Because every attempt starts at 0 and dies around the same offset, more retries do not help. This is not slow — it is non-terminating. On a connection where a 282 MB single stream cannot survive ~90 MB, fbuild can never provision this toolchain at all.

This blocked local verification of a SAMD fix (FastLED/FastLED#4015); I had to fall back to CI, where the toolchain is already provisioned.

Suggested handling

  • Retry with Range: from the byte count already on disk rather than restarting.
  • Cap retries and fail loudly with the byte offset, instead of looping indefinitely at the same place.
  • Verify the completed archive by digest, so a resumed download is still provably intact.

Segmented/parallel fetch would also help, but resume is the part that changes whether it finishes rather than how fast. Related: FastLED/FastLED#3968 and forge-ci/zccache#1469 make the same case for a content-addressed fetch with conditional GET, measured at 3.7x on a comparable payload; a shared implementation would cover both.

Environment

  • Windows 10 Pro 19045
  • FastLED master, bash compile samd21 --examples Blink
  • fbuild resolving arm-gcc 15.2.Rel1

Activity

  1. zackees commented on Aug 23, 2026

    @zackees
    MemberAuthor

    Worked around it locally, and the workaround identifies the fix precisely.

    Why it cannot converge

    There is no partial file on disk to resume from. The cache dir shows only a staging directory and a lock:

    cache/toolchains/developer-gnu/<hash>/.15.2.Rel1.install.lock
    cache/toolchains/developer-gnu/<hash>/15.2.Rel1_staging     <- empty
    

    So each failed attempt discards everything. Latest run before I gave up: 9 resets, peak 116/282 MB, roughly 1 GB transferred for zero progress. Retries cannot help when every attempt starts at byte 0 and the connection does not survive ~100 MB.

    The same download, with Range:

    curl -sL -C - --retry 3 -o armgcc.zip <url>   # in a retry loop
    COMPLETE at attempt 2 (295922350 bytes)
    

    Two attempts. Byte-exact, valid zip, 7801 entries. The origin advertises what is needed:

    HTTP/1.1 200 OK
    Content-Length: 295922350
    Accept-Ranges: bytes
    

    So the fix is not more retries or a longer timeout — it is write to disk and resume from the byte count already there. That single change turns a non-terminating download into a two-attempt one on this connection.

    Seeding the cache by hand works

    For anyone else blocked: extracting into the install layout is enough, fbuild picks it up with no further download.

    cache/toolchains/developer-gnu/<hash>/15.2.Rel1/{bin,arm-none-eabi,lib,include,libexec,share}
    cache/toolchains/developer-gnu/<hash>/15.2.Rel1/.install_complete   # 0-byte marker
    

    The ARM zip is already flat at its root, so it extracts straight in. Layout confirmed against toolchain-gccarmnoneeabi-teensy in the same cache. Remove the stale .install.lock and empty _staging left by the killed run.

    arm-none-eabi-g++.exe (Arm GNU Toolchain 15.2.Rel1 (Build arm-15.86)) 15.2.1 20251203
    

    Worth noting the marker is what makes hand-seeding viable, and also what makes the current failure total: a half-extracted staging dir with no marker leaves no usable state behind either.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions