Fixed: backups could hang at the end of a run (#394)
A backup would run to completion, borg would finish, and the job would then sit indefinitely with no output and no error until it was cancelled by hand. It affected backups of large file sets, and looked maddeningly inconsistent — the same client would complete with one exclusion list and hang with another.
Found and fixed by @ArbiterGR, who traced it to the actual mechanism, wrote the patch, and verified it against the exact configuration that reproduced it. The credit for this one is entirely his.
The agent reads borg's error stream to completion, waits for borg to exit, and then reads its standard output. That output was a pipe, and a pipe holds about 64KB. borg writes its final summary to standard output at the very end of a run; once that summary exceeds 64KB, borg blocks partway through writing it — so it never exits, so the wait never returns, and nothing ever reads the pipe that would let it continue. The comment in the code at that read asserted it was safe because borg had already exited, which is precisely what the deadlock prevents.
That explains what had made it so hard to pin down:
- Dry runs always worked. A dry run produces no final summary of that size, so the buffer never fills.
- The exclusion list appeared to be the trigger. It wasn't the exclusions themselves — changing them moved the size of the final summary across the 64KB line.
borg's output now goes to a file, which has no such limit. Reproduced before and after: with the same read order, 30KB through a pipe completes and 200KB deadlocks, while 200KB and 5MB both complete once the output goes to a file.
The cancellation path changed with it. It previously drained standard output under a timeout to guard against a leftover child process holding the pipe open; with the output on a file that particular hang is no longer reachable.
If you saw backups stall at the end — particularly on Windows, particularly with large file sets — this is very likely what you were hitting. The fix is in the agent, so clients need to be running 2.79.0 for it to take effect.
Fixed: backup plan retention could not be read back
The API accepted the six retention values on a plan but never returned them, so anything editing a plan outside the web interface had no current values to display. An editor rendering empty fields would write zeros back on save and silently discard the plan's retention policy — the kind of thing only noticed later, when archives start disappearing.
Both GET /api/v1/clients/{id}/plans and GET /api/v1/clients/{id} now return them. Negative values are preserved rather than clamped, since a negative keep count is borg's way of saying "no limit".
Agent
Agent version 2.79.0, matching the server. Clients that accept server-driven updates will pick it up on their next check-in.