<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Concurrency on tsvinc</title>
		<link>https://tsvinc.dev/tags/concurrency/</link>
		<description>Recent content in Concurrency on tsvinc</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Thu, 29 Oct 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://tsvinc.dev/tags/concurrency/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>The race detector saw my requests in order</title>
				<link>https://tsvinc.dev/posts/race-detector-saw-ordered-requests/</link>
				<pubDate>Thu, 29 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/race-detector-saw-ordered-requests/</guid>
				<description>&lt;p&gt;I run a small Go proxy on my LAN, in front of the GPU boxes that serve my local LLMs. Clients can ask it for a model by a short alias, and it looks the alias up in a map to decide where the request goes. That map can now be replaced while the proxy is running, by a config reload, so every read of it has to take a lock. A read that skips the lock is the kind of bug that does nothing at all until one request lands in the middle of a reload, and I have no interest in meeting it there.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The lock map deleted a mutex someone was waiting on</title>
				<link>https://tsvinc.dev/posts/lock-map-deleted-a-waited-mutex/</link>
				<pubDate>Tue, 27 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/lock-map-deleted-a-waited-mutex/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you have guarded per-key work in Go with a map of mutexes. Builds on &lt;a href=&#34;https://tsvinc.dev/posts/blind-review-agent-code-probes/&#34;&gt;29 of 34 passing agent runs had a blocker the hidden tests never saw&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;This series is about the A9, my 128 GB AMD Strix Halo test box (a GEEKOM A9 Mega: Ryzen AI Max+ 395, 128 GB of soldered LPDDR5X-8000), and lately about one question: can a model running on it, locally, do a developer&#39;s job as a coding agent? The study that asks it is a grid: several models, the same ticket-style tasks for each, more than one agent harness, and I grade what each run leaves behind. The grading has several layers, on the theory that any one of them can be fooled and fooling all of them at once is harder. This post is about a run that fooled every layer but one, and I wrote one of the fooled layers myself.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The shutdown grace that never ran</title>
				<link>https://tsvinc.dev/posts/shutdown-grace-never-ran/</link>
				<pubDate>Sun, 25 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/shutdown-grace-never-ran/</guid>
				<description>&lt;p&gt;The net/http documentation spends two sentences on the trap, in the comment on &lt;code&gt;Server.Shutdown&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// When Shutdown is called, [Serve], [ServeTLS], [ListenAndServe], and&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// [ListenAndServeTLS] immediately return [ErrServerClosed]. Make sure the&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// program doesn&amp;#39;t exit and waits instead for Shutdown to return.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My LAN proxy for local models did the other thing. It started &lt;code&gt;Shutdown&lt;/code&gt; in a goroutine with a five-second budget, let &lt;code&gt;ListenAndServe&lt;/code&gt; return, and returned from &lt;code&gt;main&lt;/code&gt;. Until v0.3.0, every restart cut every stream going through it within milliseconds of the &lt;code&gt;SIGTERM&lt;/code&gt;, logged nothing about the requests it cut, and exited with status 0. The proxy needs a restart after every config edit, and its streams are coding agents&#39; turns against models on two GPU boxes, which can run for minutes.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The fixes had the bugs</title>
				<link>https://tsvinc.dev/posts/fixes-had-the-bugs/</link>
				<pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/fixes-had-the-bugs/</guid>
				<description>&lt;p&gt;Marking a fix done sounds like the easy part. Write the change, write a test, watch the suite go green, tick the box. I had 45 findings for my LAN proxy for local models, from a round of research into what coding agents and other clients send and what llama.cpp&#39;s endpoints expect. I had an afternoon of fixes, and a green suite.&lt;/p&gt;&#xA;&lt;p&gt;The fixes then went through an independent re-review, pass after pass, each one starting from the findings and the code rather than from my summary of what I&#39;d done. Seven passes found 11, 8, 10, 4, 2, 1 and 0 bugs. They weren&#39;t new findings about clients. They were in the fixes, and in the fixes of the fixes, and two of them could take the whole proxy down.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The deadlock test can&#39;t see a half-held lock</title>
				<link>https://tsvinc.dev/posts/deadlock-test-half-held-lock/</link>
				<pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/deadlock-test-half-held-lock/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you have written a two-account transfer under per-account locks, and know what a mutation test is.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;At 128k context and a four-hour budget, four 27B local models ran a Zig ledger task 36 times through OpenCode. All 36 passed all 15 hidden core tests. All 36 had written their own concurrency test with real threads, because the prompt asked for one.&lt;/p&gt;&#xA;&lt;p&gt;Then the scorer removed the second account lock from each &lt;code&gt;transfer&lt;/code&gt; and ran everything again. The hidden suite failed on every mutant it could score. The models&#39; own suites failed in 4 of 11 scoreable spec runs, 0 of 9 clean review runs, and 6 of 9 test-first runs.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Zig&#39;s defer ends at the closing brace</title>
				<link>https://tsvinc.dev/posts/zig-defer-ends-at-closing-brace/</link>
				<pubDate>Mon, 12 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/zig-defer-ends-at-closing-brace/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you have guarded a critical section with a mutex and &lt;code&gt;defer unlock&lt;/code&gt; in Go.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;Moving money between two accounts under per-account locks has one famous trap, and it is the order. Lock A then B in one thread, B then A in another, and the two transfers deadlock. The textbook answer is to sort the IDs and always lock the lower one first. It is in every concurrency chapter.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
