[lxc-devel] [lxd/master] VM: Don't spin when Qemu QMP event channel is closed.
tomponline on Github
lxc-bot at linuxcontainers.org
Tue Dec 15 12:44:04 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 311 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201215/e581b79a/attachment.bin>
-------------- next part --------------
From 1f8d31f61d7f375b5fd8029d4d79d4ce6da8292e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 15 Dec 2020 12:41:08 +0000
Subject: [PATCH 1/2] lxd/instance/drivers/qmp/monitor: Handle closed event
channel from qmp package in run
Fixes #8253
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/drivers/qmp/monitor.go | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/lxd/instance/drivers/qmp/monitor.go b/lxd/instance/drivers/qmp/monitor.go
index 20c6dd4d01..ea564e6080 100644
--- a/lxd/instance/drivers/qmp/monitor.go
+++ b/lxd/instance/drivers/qmp/monitor.go
@@ -12,6 +12,7 @@ import (
"github.com/digitalocean/go-qemu/qmp"
"github.com/lxc/lxd/shared"
+ "github.com/lxc/lxd/shared/logger"
)
var monitors = map[string]*Monitor{}
@@ -126,13 +127,22 @@ func (m *Monitor) run() error {
select {
case <-m.chDisconnect:
return
- case e := <-chEvents:
- if e.Event == "" {
- continue
+ case e, more := <-chEvents:
+ // Deliver non-empty events to the event handler.
+ if m.eventHandler != nil && e.Event != "" {
+ go m.eventHandler(e.Event, e.Data)
}
- if m.eventHandler != nil {
- go m.eventHandler(e.Event, e.Data)
+ // Event channel is closed, lets disconnect.
+ if !more {
+ m.Disconnect()
+ return
+ }
+
+ if e.Event == "" {
+ logger.Warnf("Unexpected empty event received from qmp event channel")
+ time.Sleep(time.Second) // Don't busy wait if we receive a lot of these.
+ continue
}
// Check if the ringbuffer was updated (non-blocking).
From 2ab69cfc1fa49211b3fb3de0ed9ed29ac78c6e0a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 15 Dec 2020 12:41:56 +0000
Subject: [PATCH 2/2] lxd/instance/drivers/driver/qemu: Logs when instance is
stopped in getMonitorEventHandler
And removes some references to the instance in the function returned from getMonitorEventHandler so they are not kept in memory.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/drivers/driver_qemu.go | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index d01f47a3f7..b6168a3f6e 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -343,9 +343,12 @@ func (d *qemu) getStoragePool() (storagePools.Pool, error) {
}
func (d *qemu) getMonitorEventHandler() func(event string, data map[string]interface{}) {
+ // Create local variables from device properties we need so as not to keep references to device around
+ // after we have returned the callback function.
projectName := d.Project()
instanceName := d.Name()
state := d.state
+ logger := d.logger
return func(event string, data map[string]interface{}) {
if !shared.StringInSlice(event, []string{"SHUTDOWN"}) {
@@ -354,11 +357,13 @@ func (d *qemu) getMonitorEventHandler() func(event string, data map[string]inter
inst, err := instance.LoadByProjectAndName(state, projectName, instanceName)
if err != nil {
- d.logger.Error("Failed to load instance", log.Ctx{"err": err})
+ logger.Error("Failed to load instance", log.Ctx{"err": err})
return
}
if event == "SHUTDOWN" {
+ logger.Debug("Instance stopped")
+
target := "stop"
entry, ok := data["reason"]
if ok && entry == "guest-reset" {
@@ -367,7 +372,7 @@ func (d *qemu) getMonitorEventHandler() func(event string, data map[string]inter
err = inst.(*qemu).onStop(target)
if err != nil {
- d.logger.Error("Failed to cleanly stop instance", log.Ctx{"err": err})
+ logger.Error("Failed to cleanly stop instance", log.Ctx{"err": err})
return
}
}
More information about the lxc-devel
mailing list