Go 1.16.3 repairs timer insertion and module cache recovery
A timer fix protects runtime state across preemption, while a module download fix reconstructs missing checksum metadata without downloading an existing archive again.
A timer's deadline is only part of making it run. The runtime must also put it into the right data structure while execution can move between scheduling contexts. Go 1.16.3 includes a fix that protects that insertion. Its regression test repeatedly creates timers with a zero duration and checks that their notifications do not suffer an unexpectedly long delay.
The April 1 release entry lists fixes across the toolchain and runtime, including testing and time. The release announcement also announces Go 1.15.11. These are maintenance releases. The interesting details sit in the changed implementation and its tests, where ordinary promises about timers and dependency downloads acquire precise conditions.
I care about these fixes because Go's usefulness depends on behavior that application code can usually take for granted. A timer should reach its consumer, and an interrupted cache state should have a defined recovery path. Neither improvement requires a new language construct.
Timer insertion protects its scheduling context
The Go 1.16.2 to Go 1.16.3 diff changes addtimer in runtime/time.go. Before obtaining the current P and manipulating its timer heap, the function now calls acquirem. It calls releasem after waking the network poller. The new comment states the purpose directly, disabling preemption while using the P reference to avoid changing another P's heap.
The distinction is between locking a data structure and preserving the scheduling context through which the runtime reached it. Before this change, the function already took a timersLock while cleaning and updating the heap. The patch adds protection around the broader sequence. Looking only for the presence of a lock would therefore miss the invariant this change restores.
The time package regression test creates a zero-duration timer, receives from its channel, and measures elapsed time. Its loop repeats one million times and flags an iteration taking more than two seconds. The test skips short mode. Those details describe a test intended to encounter an intermittent scheduling failure, without claiming that a two-second delay is normal timer behavior.
A zero deadline makes this a useful diagnostic case. There is no intentionally long wait to explain a late notification. The test comment identifies missed timers in the scheduler as its subject and names issue 44868. Its threshold is a way to detect the regression, not a latency guarantee for applications under arbitrary load.
An existing ZIP is not a complete cache entry
Another change in the same diff repairs module-cache recovery. DownloadZip previously returned without acquiring its lock when the ZIP file existed. The new fast path requires both the archive and its ziphash file. If either is missing, the command acquires the lock and checks their state again.
This makes the cache's completion condition explicit. An archive is a data file, while its hash participates in checking the module contents. Finding the first file alone does not establish that the metadata needed by later operations is present. The code must account for an incomplete pair.
The repaired download path handles an existing archive with a missing hash by hashing the archive again. Its comment describes deletion or a filesystem crash as reasons the hash might be absent. It does not download the archive again merely to recover this metadata. The existing data is sufficient input for reconstruction.
The new hashZip helper calculates the archive hash and checks it through checkModSum before writing the hash file. Its comment says a mismatch against go.sum, or the checksum database when enabled, returns an error without writing ziphash. Recovery therefore includes validation. The command does not make the cache appear complete by recording an unchecked value.
The ordering matters for concurrent commands too. A file absent before the lock can appear while a command waits. Rechecking under the lock lets the code use work another process completed. The patch keeps recovery and the ordinary download path inside the same coordination mechanism.
Test diagnostics also depend on internal state
The testing package change addresses source locations reported through helper functions. A new regression test marks functions as helpers around a nested subtest and checks the final fatal-error message's file and line. The implementation moves conversion of helper program counters to function names into frameSkip.
This is another maintenance change whose practical value is easy to overlook. A failure message is useful only if its location points toward the call that needs attention. Helper bookkeeping participates in selecting that location, so its state must be available where frames are examined. The added test makes the expected output observable.
I appreciate a patch release that makes these existing behaviors more dependable. The changes have different users, but their evidence is concrete. Timer insertion gains a protected scheduling context, the module cache gains a validated recovery path, and test output gains a regression case for helper attribution. Each can be assessed through the implementation and the behavior its accompanying test checks.