December 4, 2019·4 min read·engineeringgohttpcontextmaintenance

Go 1.13.5 keeps HTTP connection contexts separate

A server callback could accidentally change the base context used for later connections. Go 1.13.5 gives each accepted connection a separate context variable and adds a regression test across two connections.

An immutable context value can still carry state into the wrong operation when code retains the wrong reference. Go 1.13.5 corrects an HTTP server loop that assigned a connection-specific context back to a variable reused for later connections. The next callback could then receive values attached for an earlier connection.

The December 4 release entry lists maintenance changes to the toolchain, runtime and net/http. The connection-context patch supplies a particularly useful example because its regression test checks behavior across connections. A successful request alone would not establish the required separation.

I like Go's context mechanism when the lifetime and scope of its values remain explicit. A value associated with one accepted connection should not become an implicit input to the next. This fix restores that boundary with a small change to ownership of a variable in the accept loop.

The callback result belongs to one connection

Go 1.13 introduced Server.ConnContext and Server.BaseContext, as described in its release notes. They allow applications to control contexts associated with connections and requests. The callback receives a context and the accepted network connection, then returns the context to use for that connection.

Before this patch, the accept loop assigned the callback's returned value to ctx. It then passed that variable to the goroutine serving the connection. The assignment also affected the context supplied to the callback on the next iteration, so a value added for one connection could remain in the next callback's input.

The correction introduces connCtx, initialized from ctx for each accepted connection. After the callback modifies this local reference, the serving goroutine receives connCtx. The outer ctx remains the starting point for later iterations, and the existing check still rejects a callback returning nil.

This is a reference-flow problem rather than a claim that contexts themselves mutate. A callback can return a derived context containing an additional value. Reusing that derived context as the next operation's parent is enough to extend the value's visibility beyond its intended scope.

The test deliberately creates another connection

The new regression test configures an HTTP handler to send Connection: close. That prevents the second request in the test from merely reusing the first connection. The test needs the server to accept another connection and call ConnContext again.

Inside the callback, it looks for a value under a private key. Finding a value is a failure, because the callback has not yet added the value for this connection. It then returns a derived context containing a value under that key. The second connection is the observation that distinguishes the corrected loop from the previous behavior.

The test therefore exercises a temporal property. Each callback invocation must start without the value added by the preceding invocation. A test checking only that the handler receives the new value could pass even while the context accumulates information across later connections.

The patch does not claim that every HTTP server using Go had incorrect request data. A program has to use the callback and depend on the relevant context behavior for this defect to affect its own metadata. The source change establishes the server's separation guarantee independently of any particular application key.

I find the regression test more informative than a broad claim about context safety. It names the boundary, establishes a fresh connection and checks the callback's input before adding new state. That makes the failure condition understandable without an invented application incident.

Other changes correct toolchain assumptions

The release branch history also records synchronized writes to the module command's modOnly map. A follow-up adds another lock around an access. These changes concern shared tool state, a different mechanism from the HTTP server's accidental reuse of a context reference.

Another runtime fix corrects an upper-bound comparison when locating an offset among multiple text sections. The earlier comparison included the address just after a section's end. The commit explains that an offset equal to sectaddr+sectlen is outside the section, so the upper comparison must be strict.

The compiler also stops emitting an inappropriate relocation when targeting Android on 386. Its commit explains that the Go 1.13 TLS access sequence refers to a runtime symbol and no longer needs that relocation. Processing the unnecessary relocation could crash the linker. This concerns thread-local storage access in generated code, separately from network TLS.

These maintenance changes have specific triggers. Multiple text sections, a particular target platform and shared module-command state are distinct conditions. Treating a patch release as one undifferentiated stability improvement would hide the evidence needed to understand which behavior changes for a program or build.

For the HTTP fix, the relevant artifact is a rebuilt executable containing the corrected net/http implementation. The server now derives each callback input from the preserved base context, and only the resulting connection context reaches that connection's serving goroutine. A later connection no longer inherits callback-added values through the accept loop's variable assignment.