If Close() is called before the eventLoop is scheduled, the WaitGroup counter is still 0 and Close does not wait for the eventLoop to finish. That's a race condition
If Close() is called more than once, it panics, as the code tries to write to a closed channel. It is generally good practice to make Close idempotent, to allow the defer x.Close(); /* … */ return x.Close() idiom, which is a convenient way to guarantee both that Close is called and that the error is checked.
This commit fixes both and factors the shutdown logic into a new type for readability and ease of understanding.
There are two issues with the shutdown logic:
Close()
is called before theeventLoop
is scheduled, theWaitGroup
counter is still 0 andClose
does not wait for theeventLoop
to finish. That's a race conditionClose()
is called more than once, it panics, as the code tries to write to a closed channel. It is generally good practice to makeClose
idempotent, to allow thedefer x.Close(); /* … */ return x.Close()
idiom, which is a convenient way to guarantee both thatClose
is called and that the error is checked.This commit fixes both and factors the shutdown logic into a new type for readability and ease of understanding.