mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 21:53:52 +00:00
Prevent virtual infinite loop in volume controller
In WatchPod(), if one of the two channels being watched (pod updates and events) is closed, the for/select loop turns into a tight infinite loop because the select immediately falls through due to the channel being closed. Watch them independently instead.
This commit is contained in:
@@ -18,6 +18,7 @@ package recyclerclient
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
@@ -191,6 +192,8 @@ func (c *realRecyclerClient) Event(eventtype, message string) {
|
|||||||
c.recorder(eventtype, message)
|
c.recorder(eventtype, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WatchPod watches a pod and events related to it. It sends pod updates and events over the returned channel
|
||||||
|
// It will continue until stopChannel is closed
|
||||||
func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan struct{}) (<-chan watch.Event, error) {
|
func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan struct{}) (<-chan watch.Event, error) {
|
||||||
podSelector, err := fields.ParseSelector("metadata.name=" + name)
|
podSelector, err := fields.ParseSelector("metadata.name=" + name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -217,13 +220,34 @@ func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan s
|
|||||||
}
|
}
|
||||||
|
|
||||||
eventCh := make(chan watch.Event, 30)
|
eventCh := make(chan watch.Event, 30)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(eventCh)
|
||||||
|
wg.Wait()
|
||||||
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer eventWatch.Stop()
|
defer eventWatch.Stop()
|
||||||
|
defer wg.Done()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case _ = <-stopChannel:
|
||||||
|
return
|
||||||
|
case eventEvent, ok := <-eventWatch.ResultChan():
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
eventCh <- eventEvent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
defer podWatch.Stop()
|
defer podWatch.Stop()
|
||||||
defer close(eventCh)
|
defer wg.Done()
|
||||||
var podWatchChannelClosed bool
|
|
||||||
var eventWatchChannelClosed bool
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stopChannel:
|
case <-stopChannel:
|
||||||
@@ -231,19 +255,10 @@ func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan s
|
|||||||
|
|
||||||
case podEvent, ok := <-podWatch.ResultChan():
|
case podEvent, ok := <-podWatch.ResultChan():
|
||||||
if !ok {
|
if !ok {
|
||||||
podWatchChannelClosed = true
|
return
|
||||||
} else {
|
} else {
|
||||||
eventCh <- podEvent
|
eventCh <- podEvent
|
||||||
}
|
}
|
||||||
case eventEvent, ok := <-eventWatch.ResultChan():
|
|
||||||
if !ok {
|
|
||||||
eventWatchChannelClosed = true
|
|
||||||
} else {
|
|
||||||
eventCh <- eventEvent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if podWatchChannelClosed && eventWatchChannelClosed {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
Reference in New Issue
Block a user