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