resources: aws: ec2: Fix deadlock on rare error scenarios
If we get an error in the Watch loop, it will send this on awsChan, which will cause Watch to loop. However, in this scenario it will never cause closeChan to close, and we will deadlock because we have a waitGroup in a helper goroutine which is waiting on this channel to close the context. Normally this wouldn't be an issue, but since we have more than one goroutine (with associated waitGroup) it is. It's also good practice to close all the channels to help avoid this kind of bug. This patch also moves the waitGroup Wait into a more logical place for visibility.
This commit is contained in:
@@ -190,6 +190,8 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
if err := obj.Running(); err != nil {
|
if err := obj.Running(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer obj.wg.Wait()
|
||||||
|
defer close(obj.closeChan)
|
||||||
ctx, cancel := context.WithCancel(context.TODO())
|
ctx, cancel := context.WithCancel(context.TODO())
|
||||||
obj.wg.Add(1)
|
obj.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@@ -200,7 +202,6 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
obj.wg.Add(1)
|
obj.wg.Add(1)
|
||||||
defer obj.wg.Wait()
|
|
||||||
go func() {
|
go func() {
|
||||||
defer obj.wg.Done()
|
defer obj.wg.Done()
|
||||||
defer close(obj.awsChan)
|
defer close(obj.awsChan)
|
||||||
@@ -433,7 +434,6 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
select {
|
select {
|
||||||
case event := <-obj.Events():
|
case event := <-obj.Events():
|
||||||
if exit, send = obj.ReadEvent(event); exit != nil {
|
if exit, send = obj.ReadEvent(event); exit != nil {
|
||||||
close(obj.closeChan)
|
|
||||||
return *exit
|
return *exit
|
||||||
}
|
}
|
||||||
case msg, ok := <-obj.awsChan:
|
case msg, ok := <-obj.awsChan:
|
||||||
|
|||||||
Reference in New Issue
Block a user