qemu: wait on disconnected channel in qmp shutdown

That is how govmm ensures us that the qmp channel has been cleaned
up entirely.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
Peng Tao 2018-07-31 18:18:26 +08:00
parent c8b4fabc37
commit 44a3a441aa
2 changed files with 27 additions and 4 deletions

View File

@ -25,9 +25,10 @@ import (
)
type qmpChannel struct {
ctx context.Context
path string
qmp *govmmQemu.QMP
ctx context.Context
path string
qmp *govmmQemu.QMP
disconn chan struct{}
}
// CPUDevice represents a CPU device which was hot-added in a running VM
@ -514,6 +515,7 @@ func (q *qemu) waitSandbox(timeout int) error {
cfg := govmmQemu.QMPConfig{Logger: newQMPLogger()}
var qmp *govmmQemu.QMP
var disconnectCh chan struct{}
var ver *govmmQemu.QMPVersion
var err error
@ -521,7 +523,7 @@ func (q *qemu) waitSandbox(timeout int) error {
q.qmpShutdown()
timeStart := time.Now()
for {
disconnectCh := make(chan struct{})
disconnectCh = make(chan struct{})
qmp, ver, err = govmmQemu.QMPStart(q.qmpMonitorCh.ctx, q.qmpMonitorCh.path, cfg, disconnectCh)
if err == nil {
break
@ -534,6 +536,7 @@ func (q *qemu) waitSandbox(timeout int) error {
time.Sleep(time.Duration(50) * time.Millisecond)
}
q.qmpMonitorCh.qmp = qmp
q.qmpMonitorCh.disconn = disconnectCh
defer q.qmpShutdown()
qemuMajorVersion = ver.Major
@ -619,6 +622,7 @@ func (q *qemu) qmpSetup() error {
return err
}
q.qmpMonitorCh.qmp = qmp
q.qmpMonitorCh.disconn = disconnectCh
return nil
}
@ -626,7 +630,11 @@ func (q *qemu) qmpSetup() error {
func (q *qemu) qmpShutdown() {
if q.qmpMonitorCh.qmp != nil {
q.qmpMonitorCh.qmp.Shutdown()
// wait on disconnected channel to be sure that the qmp channel has
// been closed cleanly.
<-q.qmpMonitorCh.disconn
q.qmpMonitorCh.qmp = nil
q.qmpMonitorCh.disconn = nil
}
}

View File

@ -345,3 +345,18 @@ func TestHotplugUnsupportedDeviceType(t *testing.T) {
_, err = q.hotplugRemoveDevice(&memoryDevice{0, 128}, fsDev)
assert.Error(err)
}
func TestQMPSetupShutdown(t *testing.T) {
assert := assert.New(t)
qemuConfig := newQemuConfig()
q := &qemu{
config: qemuConfig,
}
q.qmpShutdown()
q.qmpMonitorCh.qmp = &govmmQemu.QMP{}
err := q.qmpSetup()
assert.Nil(err)
}