GetDB can open the same event database twice, and closing the loser drops the winner's file locks #291
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the review of #287. Pre-existing; that PR does not introduce it.
WebhookDBManager.GetDB(internal/database/webhook_db_manager.go:85-105) uses an optimisticsync.Mappattern:Load, thenopenDBon a miss, thenLoadOrStore. Two goroutines racing on the same webhook can therefore both open the SAMEevents-*.db, and the one that losesLoadOrStorethen callsClose()on its handle.That close is the problem. On POSIX,
close()on ANY file descriptor referring to an inode drops everyfcntllock this process holds on that inode — including the winner's. So the loser's cleanup can silently strip the surviving handle's locks.Why it is latent rather than urgent:
DATA_DIRlock from #201.Why it is worth recording anyway: the consequence is not an error, it is silently weakened locking on a handle that keeps working. Nothing would surface it until something else depended on those locks. And #256 has just made the SQLite layer's locking behaviour load-bearing in a way it was not before.
Definition of done
singleflightso the second caller waits rather than opening its own handle and discarding it. Do not solve it by leaking the loser's handle instead of closing it — that trades a lock bug for an fd leak.Not milestoned: no known failure, and the cross-process case is blocked by the startup lock.