Skip to content

Commit

Permalink
Fix send on closed channel panic (#8470)
Browse files Browse the repository at this point in the history
When the performance data is out of order, channel should be closed
by the producer, but not consumer or other thread.
  • Loading branch information
wjun authored Feb 21, 2019
1 parent 57fd7f5 commit 20edfa4
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions lib/apiservers/engine/backends/convert/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (cs *ContainerStats) Listen() *io.PipeWriter {
doc := json.NewEncoder(cs.config.Out)

// channel to transfer metric from decoder to encoder
metric := make(chan performance.VMMetrics)
metric := make(chan *types.StatsJSON)

// if we aren't streaming and the container is not running, then create an empty
// docker stat to return
Expand All @@ -145,7 +145,6 @@ func (cs *ContainerStats) Listen() *io.PipeWriter {
// go routine to stop on Context.Cancel
go func() {
<-cs.config.Ctx.Done()
close(metric)
cs.Stop()
}()

Expand All @@ -155,6 +154,7 @@ func (cs *ContainerStats) Listen() *io.PipeWriter {
for {
select {
case <-cs.config.Ctx.Done():
close(metric)
return
default:
for dec.More() {
Expand All @@ -163,10 +163,20 @@ func (cs *ContainerStats) Listen() *io.PipeWriter {
if err != nil {
log.Errorf("container metric decoding error for container(%s): %s", cs.config.ContainerID, err)
cs.config.Cancel()
close(metric)
return
}
// convert the Stat to docker struct
stat, err := cs.ToContainerStats(&vmm)
if err != nil {
log.Errorf("container metric conversion error for container(%s): %s", cs.config.ContainerID, err)
cs.config.Cancel()
close(metric)
return
}
// send the decoded metric for transform and encoding
if cs.IsListening() {
metric <- vmm
metric <- stat
}
}
}
Expand All @@ -183,13 +193,7 @@ func (cs *ContainerStats) Listen() *io.PipeWriter {
case <-cs.config.Ctx.Done():
ticker.Stop()
return
case nm := <-metric:
// convert the Stat to docker struct
stat, err := cs.ToContainerStats(&nm)
if err != nil {
log.Errorf("container metric conversion error for container(%s): %s", cs.config.ContainerID, err)
cs.config.Cancel()
}
case stat := <-metric:
if stat != nil {
cs.preDockerStat = stat
}
Expand Down

0 comments on commit 20edfa4

Please sign in to comment.