Release session resources on partial-setup and error paths
main·
Commit
Two leaks in the syncer session lifecycle:
- newSession opened the source transport (and started the memory-measurement ticker goroutine) before listing refs and setting up the target. If any of those steps failed it returned nil, err, so the caller had no session to finish() — leaking the source conn (an SSH transport spawns a process), a half-open target conn, and the ticker goroutine.
- finish() never stopped the measurement ticker; it was only stopped when a Result was built, so any early error return from runSync et al. leaked the goroutine even on a fully-constructed session.
Add a success-guarded deferred cleanup in newSession that calls finish() unless the session is handed back, hand the target conn to the session as soon as it is opened so cleanup can close it, and have finish() also invoke the sync.Once-guarded measurementDone so the ticker stops on every path.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Entire-Checkpoint: e6526831fa74