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 { type qmpChannel struct {
ctx context.Context ctx context.Context
path string path string
qmp *govmmQemu.QMP qmp *govmmQemu.QMP
disconn chan struct{}
} }
// CPUDevice represents a CPU device which was hot-added in a running VM // 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()} cfg := govmmQemu.QMPConfig{Logger: newQMPLogger()}
var qmp *govmmQemu.QMP var qmp *govmmQemu.QMP
var disconnectCh chan struct{}
var ver *govmmQemu.QMPVersion var ver *govmmQemu.QMPVersion
var err error var err error
@ -521,7 +523,7 @@ func (q *qemu) waitSandbox(timeout int) error {
q.qmpShutdown() q.qmpShutdown()
timeStart := time.Now() timeStart := time.Now()
for { for {
disconnectCh := make(chan struct{}) disconnectCh = make(chan struct{})
qmp, ver, err = govmmQemu.QMPStart(q.qmpMonitorCh.ctx, q.qmpMonitorCh.path, cfg, disconnectCh) qmp, ver, err = govmmQemu.QMPStart(q.qmpMonitorCh.ctx, q.qmpMonitorCh.path, cfg, disconnectCh)
if err == nil { if err == nil {
break break
@ -534,6 +536,7 @@ func (q *qemu) waitSandbox(timeout int) error {
time.Sleep(time.Duration(50) * time.Millisecond) time.Sleep(time.Duration(50) * time.Millisecond)
} }
q.qmpMonitorCh.qmp = qmp q.qmpMonitorCh.qmp = qmp
q.qmpMonitorCh.disconn = disconnectCh
defer q.qmpShutdown() defer q.qmpShutdown()
qemuMajorVersion = ver.Major qemuMajorVersion = ver.Major
@ -619,6 +622,7 @@ func (q *qemu) qmpSetup() error {
return err return err
} }
q.qmpMonitorCh.qmp = qmp q.qmpMonitorCh.qmp = qmp
q.qmpMonitorCh.disconn = disconnectCh
return nil return nil
} }
@ -626,7 +630,11 @@ func (q *qemu) qmpSetup() error {
func (q *qemu) qmpShutdown() { func (q *qemu) qmpShutdown() {
if q.qmpMonitorCh.qmp != nil { if q.qmpMonitorCh.qmp != nil {
q.qmpMonitorCh.qmp.Shutdown() 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.qmp = nil
q.qmpMonitorCh.disconn = nil
} }
} }

View File

@ -345,3 +345,18 @@ func TestHotplugUnsupportedDeviceType(t *testing.T) {
_, err = q.hotplugRemoveDevice(&memoryDevice{0, 128}, fsDev) _, err = q.hotplugRemoveDevice(&memoryDevice{0, 128}, fsDev)
assert.Error(err) 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)
}