replace close() with actually sending a value to .EndOfStoredEvents and .Closed channels.

I thought `close()` would be nice because it would be cheap and not lock the goroutine while waiting for the receiver to acknowledge the thing, but turns out it introduces the serious risk of users putting <- sub.EndOfStoredEvents in the same for { select {} } statement as sub.Events, for example, and they they get into an infinite loop.

we had this same problem here inside this same library, and what is fixed in 242af0bf76 by @mattn.
This commit is contained in:
fiatjaf
2024-01-01 10:16:07 -03:00
parent 3afa6fc5f6
commit 5938a71146
2 changed files with 56 additions and 3 deletions

View File

@@ -106,15 +106,16 @@ func (sub *Subscription) dispatchEose() {
if sub.eosed.CompareAndSwap(false, true) {
go func() {
sub.storedwg.Wait()
close(sub.EndOfStoredEvents)
sub.EndOfStoredEvents <- struct{}{}
}()
}
}
func (sub *Subscription) dispatchClosed(reason string) {
if sub.closed.CompareAndSwap(false, true) {
sub.ClosedReason <- reason
close(sub.ClosedReason)
go func() {
sub.ClosedReason <- reason
}()
}
}