From ac6dc96d69b27fac0b8b2e0766f15ceef99af098 Mon Sep 17 00:00:00 2001 From: Mikhail Klementev Date: Sat, 22 Sep 2018 07:28:08 +0000 Subject: [PATCH] Implements timeout for qemu --- qemu-kernel.go | 23 ++++++++++++++++++----- qemu-kernel_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/qemu-kernel.go b/qemu-kernel.go index 77a82aa..86ddbaa 100644 --- a/qemu-kernel.go +++ b/qemu-kernel.go @@ -70,6 +70,13 @@ type QemuSystem struct { Cpus int Memory int + // Timeout works after Start invocation + Timeout time.Duration + KilledByTimeout bool + + Died bool + sshAddrPort string + // accessible while qemu is runned cmd *exec.Cmd pipe struct { @@ -77,8 +84,6 @@ type QemuSystem struct { stderr io.ReadCloser stdout io.ReadCloser } - died bool - sshAddrPort string // accessible after qemu is closed Stdout, Stderr string @@ -197,15 +202,23 @@ func (q *QemuSystem) Start() (err error) { q.Stdout, _ = readUntilEOF(q.pipe.stdout) q.Stderr, _ = readUntilEOF(q.pipe.stderr) q.exitErr = q.cmd.Wait() - q.died = true + q.Died = true }() time.Sleep(time.Second / 10) // wait for immediately die - if q.died { + if q.Died { err = errors.New("qemu died immediately: " + q.Stderr) } + if q.Timeout != 0 { + go func() { + time.Sleep(q.Timeout) + q.KilledByTimeout = true + q.Stop() + }() + } + return } @@ -215,7 +228,7 @@ func (q *QemuSystem) Stop() { fmt.Fprintf(q.pipe.stdin, "%cx", 1) // wait for die time.Sleep(time.Second / 10) - if !q.died { + if !q.Died { q.cmd.Process.Signal(syscall.SIGTERM) time.Sleep(time.Second / 10) q.cmd.Process.Signal(syscall.SIGKILL) diff --git a/qemu-kernel_test.go b/qemu-kernel_test.go index 6832d03..71a25ef 100644 --- a/qemu-kernel_test.go +++ b/qemu-kernel_test.go @@ -8,6 +8,7 @@ import ( "net" "strings" "testing" + "time" ) func TestQemuSystemNew_InvalidKernelPath(t *testing.T) { @@ -55,6 +56,30 @@ func TestQemuSystemStart(t *testing.T) { qemu.Stop() } +func TestQemuSystemStart_Timeout(t *testing.T) { + kernel := Kernel{Name: "Host kernel", Path: testConfigVmlinuz} + qemu, err := NewQemuSystem(X86_64, kernel, "/bin/sh") + if err != nil { + t.Fatal(err) + } + + qemu.Timeout = time.Second + + if err = qemu.Start(); err != nil { + t.Fatal(err) + } + + time.Sleep(2 * time.Second) + + if !qemu.Died { + t.Fatal("qemu does not died :c") + } + + if !qemu.KilledByTimeout { + t.Fatal("qemu died not because of timeout O_o") + } +} + func TestGetFreeAddrPort(t *testing.T) { addrPort := getFreeAddrPort() ln, err := net.Listen("tcp", addrPort) @@ -71,6 +96,8 @@ func startTestQemu() (q *QemuSystem, err error) { return } + q.Timeout = 10 * time.Second + if err = q.Start(); err != nil { return }