Skip to content

Make graceful close, servecontent, and HTTP/2 error responses trim-safe - #1399

Merged
quinnj merged 2 commits into
masterfrom
fix/trim-graceful-close
Oct 14, 2026
Merged

quinnj merged 2 commits into
masterfrom
fix/trim-graceful-close

Conversation

@quinnj

@quinnj quinnj commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Two places where a natively built (juliac --trim=safe) server on HTTP.jl 2.9 hits dynamic dispatch. Both turned up while moving LeagueEasy onto registered HTTP.jl.

Graceful close(server)

HTTP/2 connections stored their shutdown notification as a closure in a Function-typed field. A trimmed app that called close(server) hit an unresolved call. HTTP's own trim workloads use forceclose, which skips this path, so the tests never caught it. The shutdown state is now a concrete struct. The client/server trim workload now closes its server gracefully.

servecontent response types

  • Response's body keyword defaulted to the nobody vector, so inference couldn't fold the "no keyword body" check. Every keyword-built response picked up an extra Response{Vector{UInt8}} type.
  • servecontent was also annotated ::Response.

Together, callers saw the abstract HTTP.Response, so reading or writing its body was dynamically dispatched. A natively built server failed to verify when serving a byte range.

The keyword now defaults to a private singleton, and the annotation is gone. servecontent over bytes now infers three concrete response types. An explicit body=HTTP.nobody keeps its meaning. The file-server trim workload now reads a servecontent range body.

HTTP/2 status responses

The HTTP/2 server built its 500 responses with a request= keyword typed as a union of request types. A union-typed keyword makes the keyword call dynamically dispatched. Older inference happened to resolve these calls. On Julia 1.14-dev, after the body-keyword change, they became 4 verifier errors per server specialization. The request is now set after construction.

Validation

  • Trim workloads, Julia 1.13.1, before and after:
    • graceful close: 2 verifier errors → 0;
    • range body: 4 → 0.
      Both binaries run.
  • Full Pkg.test() passes locally on Julia 1.13.1, including all 81 trim checks.
  • Servo's trim workload serves a real server through Servo.httphandler, with buffered and streaming responses and a graceful close.
    • Against this branch, built with a 1.14-dev Julia that carries the upstream ScopedValues fix: 0 verifier errors, and the binary passes.
    • On stock 1.13.1: only the known upstream ScopedValues findings.
  • Downstream: LeagueEasy's native server build verifies with 0 errors on registered 2.9.0, minus its graceful-close fallback, and a live SSE stream works in the native binary.

🤖 Generated with Claude Code

quinnj and others added 2 commits October 14, 2026 00:49
HTTP/2 connections stored their shutdown notification as a closure in a
Function-typed field, so close(server) in a juliac --trim build had an
unresolved call. Store the HTTP/2 shutdown state in a concrete struct.

The client/server trim workload now closes its server gracefully; the
other workloads keep forceclose, which skipped this path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Response's body keyword defaulted to the nobody vector, so inference could
not fold the "no keyword body" check and every keyword-built response
gained a Response{Vector{UInt8}} type. servecontent also declared an
abstract ::Response return. Together, callers saw the abstract
HTTP.Response, and reading or writing its body was dynamically dispatched
under juliac --trim (a servecontent byte range in a natively built
server). Default the keyword to a private singleton and drop the
annotation: servecontent over bytes now infers three concrete response
types. An explicit body=HTTP.nobody keeps its meaning.

The file-server trim workload now reads a servecontent range body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.80%. Comparing base (f9eaa66) to head (a582b01).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1399   +/-   ##
=======================================
  Coverage   90.80%   90.80%           
=======================================
  Files          31       31           
  Lines       12838    12841    +3     
=======================================
+ Hits        11657    11660    +3     
  Misses       1181     1181           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@quinnj
quinnj merged commit 8bee674 into master Oct 14, 2026
10 checks passed
@quinnj
quinnj deleted the fix/trim-graceful-close branch October 14, 2026 12:54
@quinnj quinnj changed the title Make graceful close and servecontent trim-safe Make graceful close, servecontent, and HTTP/2 error responses trim-safe Oct 14, 2026
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