diff --git a/src/runtime/pkg/govmm/qemu/examples_test.go b/src/runtime/pkg/govmm/qemu/examples_test.go index 03e52b87ac..1a3f2e8ffb 100644 --- a/src/runtime/pkg/govmm/qemu/examples_test.go +++ b/src/runtime/pkg/govmm/qemu/examples_test.go @@ -27,13 +27,16 @@ func Example() { // resources params = append(params, "-m", "370", "-smp", "cpus=2") - // LaunchCustomQemu should return as soon as the instance has launched as we - // are using the --daemonize flag. It will set up a unix domain socket - // called /tmp/qmp-socket that we can use to manage the instance. - _, err := qemu.LaunchCustomQemu(context.Background(), "", params, nil, nil, nil) + // LaunchCustomQemu should return immediately. We must then wait + // the returned process to terminate as we are using the --daemonize + // flag. + // It will set up a unix domain socket called /tmp/qmp-socket that we + // can use to manage the instance. + proc, err := qemu.LaunchCustomQemu(context.Background(), "", params, nil, nil, nil) if err != nil { panic(err) } + proc.Wait() // This channel will be closed when the instance dies. disconnectedCh := make(chan struct{}) diff --git a/src/runtime/pkg/govmm/qemu/qemu.go b/src/runtime/pkg/govmm/qemu/qemu.go index d665c0c7a4..cecd2d2bb7 100644 --- a/src/runtime/pkg/govmm/qemu/qemu.go +++ b/src/runtime/pkg/govmm/qemu/qemu.go @@ -14,7 +14,6 @@ package qemu import ( - "bytes" "context" "fmt" "log" @@ -2985,12 +2984,8 @@ func (config *Config) appendFwCfg(logger QMPLog) { // // The Config parameter contains a set of qemu parameters and settings. // -// This function writes its log output via logger parameter. -// -// The function will block until the launched qemu process exits. "", nil -// will be returned if the launch succeeds. Otherwise a string containing -// the contents of stderr + a Go error object will be returned. -func LaunchQemu(config Config, logger QMPLog) (string, error) { +// See LaunchCustomQemu for more information. +func LaunchQemu(config Config, logger QMPLog) (*exec.Cmd, error) { config.appendName() config.appendUUID() config.appendMachine() @@ -3013,7 +3008,7 @@ func LaunchQemu(config Config, logger QMPLog) (string, error) { config.appendSeccompSandbox() if err := config.appendCPUs(); err != nil { - return "", err + return nil, err } ctx := config.Ctx @@ -3044,17 +3039,15 @@ func LaunchQemu(config Config, logger QMPLog) (string, error) { // // This function writes its log output via logger parameter. // -// The function will block until the launched qemu process exits. "", nil -// will be returned if the launch succeeds. Otherwise a string containing -// the contents of stderr + a Go error object will be returned. +// The function returns cmd, nil where cmd is a Go exec.Cmd object +// representing the QEMU process if launched successfully. Otherwise +// nil, err where err is a Go error object is returned. func LaunchCustomQemu(ctx context.Context, path string, params []string, fds []*os.File, - attr *syscall.SysProcAttr, logger QMPLog) (string, error) { + attr *syscall.SysProcAttr, logger QMPLog) (*exec.Cmd, error) { if logger == nil { logger = qmpNullLogger{} } - errStr := "" - if path == "" { path = "qemu-system-x86_64" } @@ -3068,15 +3061,12 @@ func LaunchCustomQemu(ctx context.Context, path string, params []string, fds []* cmd.SysProcAttr = attr - var stderr bytes.Buffer - cmd.Stderr = &stderr logger.Infof("launching %s with: %v", path, params) - err := cmd.Run() + err := cmd.Start() if err != nil { logger.Errorf("Unable to launch %s: %v", path, err) - errStr = stderr.String() - logger.Errorf("%s", errStr) + return nil, err } - return errStr, err + return cmd, nil } diff --git a/src/runtime/virtcontainers/qemu.go b/src/runtime/virtcontainers/qemu.go index f2d4711371..8781747987 100644 --- a/src/runtime/virtcontainers/qemu.go +++ b/src/runtime/virtcontainers/qemu.go @@ -941,17 +941,16 @@ func (q *qemu) StartVM(ctx context.Context, timeout int) error { } - var strErr string - strErr, err = govmmQemu.LaunchQemu(q.qemuConfig, newQMPLogger()) + qemuCmd, err := govmmQemu.LaunchQemu(q.qemuConfig, newQMPLogger()) if err != nil { - if q.config.Debug && q.qemuConfig.LogFile != "" { - b, err := os.ReadFile(q.qemuConfig.LogFile) - if err == nil { - strErr += string(b) - } - } - q.Logger().WithError(err).Errorf("failed to launch qemu: %s", strErr) - return fmt.Errorf("failed to launch qemu: %s, error messages from qemu log: %s", err, strErr) + q.Logger().WithError(err).Error("failed to launch qemu") + return fmt.Errorf("failed to launch qemu: %s", err) + } + if q.qemuConfig.Knobs.Daemonize { + // LaunchQemu returns a handle on the upper QEMU process. + // Wait for it to exit to assume that the QEMU daemon was + // actually started. + qemuCmd.Wait() } err = q.waitVM(ctx, qmpConn, timeout)