Case study / mark

A second Close returned before shutdown finished.

A small concurrency bug in a Go tool, found with Go support that is not released yet.

Go is in test and not released. arnx 0.1.11 reviews Python, JavaScript, TypeScript and Rust. This review ran on a development build with Go support. You cannot reproduce it with the version on npm today.

mark syncs Markdown files to Confluence. A review of its recent commits produced a test showing that a second, concurrent Close returned while the resource was still stopping, against what the function's own comment promises. The fix was merged upstream on 2026-11-11 as kovetskiy/mark#1244.

1. Repository and reviewed commit

kovetskiy/mark, the last ten commits on master on 2026-11-10, range 3113164..a18f773: 29 files, 1,694 lines added and 399 removed. arnx had no earlier contact with the repository.

2. Expected behavior

internal/lazy starts a resource on first use and stops it on Close. mark uses it for the headless browser and the mermaid engine. The comment on Close says whatever was made is stopped before Close returns. That should hold for every caller.

3. Actual behavior

The first Close set a closed flag, released the lock and ran the stop function, which can take a while. A second Close arriving meanwhile saw the flag and returned at once. Its caller could carry on while the resource was still shutting down.

4. Suspected defect

Before any test ran, the second hunter (gpt-6.1-sol) suspected: Concurrent Close calls can return before resource shutdown has completed.

5. Generated test

The reviewer wrote TestSecondCloseWaitsForStop: start a resource whose stop function blocks, call Close in one goroutine, call it again in another, and check that the second call has not returned while the first is still stopping.

6. Execution result

From review.md, quoted
### F1 · confirmed by the second opinion
- Test: `arnx_generated/lazy_arnx/lazy_arnx_test.go::TestSecondCloseWaitsForStop`
- Failure: `lazy_arnx_test.go:33: second Close returned while the resource was still stopping`
- Reviewer: The first Close sets isClosed, then stops the resource outside the lock.
  A second concurrent Close sees isClosed and returns at once. Close's documented
  guarantee that shutdown is finished on return does not hold for the second caller.
- Before the change (unknown): could not run on the code before the change

The review wrote 12 tests; 11 passed in every run and this one failed in every run. It took 1 minute 54 seconds and cost $0.58. Reviewer and second opinion: claude-sonnet-5-5. These numbers come from our local review record, not from a public page.

7. Correction

The fix adds a channel that is closed when the first Close has finished stopping. A later Close waits on it. Closing twice in a row still returns at once. The change is 14 lines of code in internal/lazy/lazy.go and one test. The fix was drafted with AI assistance; the owner of arnx reviewed it and opened the pull request, with an AI disclosure.

8. Verification result

From the pull request: TestSecondCloseWaitsForStop fails on master and passes with the fix. The race detector ran the package 30 times clean, and go test ./... passes. A maintainer merged it about an hour after it was opened, with the comment Thanks!

9. Upstream references

10. Limitations and observations

Last reviewed 2026-11-12 against arnx 0.1.11. The release documentation is canonical for your installed version.