Skip to content

Commit 6b7dabd

Browse files
committed
Move sleeps
1 parent 09af36c commit 6b7dabd

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

lib/hypervisor/qemu/process.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ import (
2121
"gvisor.dev/gvisor/pkg/cleanup"
2222
)
2323

24+
// Timeout constants for QEMU operations
25+
const (
26+
// socketWaitTimeout is how long to wait for QMP socket to become available after process start
27+
socketWaitTimeout = 10 * time.Second
28+
29+
// migrationTimeout is how long to wait for incoming migration to complete during restore
30+
migrationTimeout = 30 * time.Second
31+
32+
// migrationPollInterval is how often to poll migration status
33+
migrationPollInterval = 50 * time.Millisecond
34+
35+
// socketPollInterval is how often to check if socket is ready
36+
socketPollInterval = 50 * time.Millisecond
37+
38+
// socketDialTimeout is timeout for individual socket connection attempts
39+
socketDialTimeout = 100 * time.Millisecond
40+
)
41+
2442
func init() {
2543
hypervisor.RegisterSocketName(hypervisor.TypeQEMU, "qemu.sock")
2644
}
@@ -94,6 +112,8 @@ func (s *Starter) GetVersion(p *paths.Paths) (string, error) {
94112
// StartVM launches QEMU with the VM configuration and returns a Hypervisor client.
95113
// QEMU receives all configuration via command-line arguments at process start.
96114
func (s *Starter) StartVM(ctx context.Context, p *paths.Paths, version string, socketPath string, config hypervisor.VMConfig) (int, hypervisor.Hypervisor, error) {
115+
log := logger.FromContext(ctx)
116+
97117
// Get binary path
98118
binaryPath, err := s.GetBinaryPath(p, version)
99119
if err != nil {
@@ -157,7 +177,7 @@ func (s *Starter) StartVM(ctx context.Context, p *paths.Paths, version string, s
157177
defer cu.Clean()
158178

159179
// Wait for socket to be ready
160-
if err := waitForSocket(socketPath, 10*time.Second); err != nil {
180+
if err := waitForSocket(socketPath, socketWaitTimeout); err != nil {
161181
vmmLogPath := filepath.Join(logsDir, "vmm.log")
162182
if logData, readErr := os.ReadFile(vmmLogPath); readErr == nil && len(logData) > 0 {
163183
return 0, nil, fmt.Errorf("%w; vmm.log: %s", err, string(logData))
@@ -175,7 +195,7 @@ func (s *Starter) StartVM(ctx context.Context, p *paths.Paths, version string, s
175195
// QEMU migration files only contain memory state, not device config
176196
if err := saveVMConfig(instanceDir, config); err != nil {
177197
// Non-fatal - restore just won't work
178-
// Log would be nice but we don't have logger here
198+
log.WarnContext(ctx, "failed to save VM config for restore", "error", err)
179199
}
180200

181201
// Success - release cleanup to prevent killing the process
@@ -290,7 +310,7 @@ func (s *Starter) RestoreVM(ctx context.Context, p *paths.Paths, version string,
290310
// QEMU loads the migration data from the exec subprocess
291311
// After loading, VM is in paused state and ready for 'cont'
292312
migrationWaitStart := time.Now()
293-
if err := waitForMigrationComplete(hv.client, 30*time.Second); err != nil {
313+
if err := waitForMigrationComplete(hv.client, migrationTimeout); err != nil {
294314
return 0, nil, fmt.Errorf("wait for migration: %w", err)
295315
}
296316
log.DebugContext(ctx, "migration complete", "duration_ms", time.Since(migrationWaitStart).Milliseconds())
@@ -308,13 +328,13 @@ func waitForMigrationComplete(client *Client, timeout time.Duration) error {
308328
info, err := client.QueryMigration()
309329
if err != nil {
310330
// Ignore errors during migration
311-
time.Sleep(100 * time.Millisecond)
331+
time.Sleep(migrationPollInterval)
312332
continue
313333
}
314334

315335
if info.Status == nil {
316336
// No migration status yet, might be loading
317-
time.Sleep(100 * time.Millisecond)
337+
time.Sleep(migrationPollInterval)
318338
continue
319339
}
320340

@@ -330,7 +350,7 @@ func waitForMigrationComplete(client *Client, timeout time.Duration) error {
330350
return nil
331351
}
332352

333-
time.Sleep(100 * time.Millisecond)
353+
time.Sleep(migrationPollInterval)
334354
}
335355
return fmt.Errorf("migration timeout")
336356
}
@@ -392,7 +412,7 @@ func qemuInstallHint() string {
392412

393413
// isSocketInUse checks if a Unix socket is actively being used
394414
func isSocketInUse(socketPath string) bool {
395-
conn, err := net.DialTimeout("unix", socketPath, 100*time.Millisecond)
415+
conn, err := net.DialTimeout("unix", socketPath, socketDialTimeout)
396416
if err != nil {
397417
return false
398418
}
@@ -404,12 +424,12 @@ func isSocketInUse(socketPath string) bool {
404424
func waitForSocket(socketPath string, timeout time.Duration) error {
405425
deadline := time.Now().Add(timeout)
406426
for time.Now().Before(deadline) {
407-
conn, err := net.DialTimeout("unix", socketPath, 100*time.Millisecond)
427+
conn, err := net.DialTimeout("unix", socketPath, socketDialTimeout)
408428
if err == nil {
409429
conn.Close()
410430
return nil
411431
}
412-
time.Sleep(50 * time.Millisecond)
432+
time.Sleep(socketPollInterval)
413433
}
414434
return fmt.Errorf("timeout waiting for socket")
415435
}

lib/hypervisor/qemu/qemu.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (q *QEMU) Snapshot(ctx context.Context, destPath string) error {
135135
}
136136

137137
// Wait for migration to complete
138-
if err := q.client.WaitMigration(ctx, 30*time.Second); err != nil {
138+
if err := q.client.WaitMigration(ctx, migrationTimeout); err != nil {
139139
Remove(q.socketPath)
140140
return fmt.Errorf("wait migration: %w", err)
141141
}

lib/hypervisor/qemu/qmp.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ import (
1010
"github.com/digitalocean/go-qemu/qmp/raw"
1111
)
1212

13+
// QMP client timeout constants
14+
const (
15+
// qmpConnectTimeout is the timeout for connecting to the QMP socket
16+
qmpConnectTimeout = 1 * time.Second
17+
18+
// qmpMigrationPollInterval is how often to poll migration status in WaitMigration
19+
qmpMigrationPollInterval = 50 * time.Millisecond
20+
)
21+
1322
// Client wraps go-qemu's Domain and raw.Monitor with convenience methods.
1423
type Client struct {
1524
domain *qemu.Domain
@@ -19,7 +28,7 @@ type Client struct {
1928

2029
// NewClient creates a new QEMU client connected to the given socket.
2130
func NewClient(socketPath string) (*Client, error) {
22-
mon, err := qmp.NewSocketMonitor("unix", socketPath, 2*time.Second)
31+
mon, err := qmp.NewSocketMonitor("unix", socketPath, qmpConnectTimeout)
2332
if err != nil {
2433
return nil, fmt.Errorf("create socket monitor: %w", err)
2534
}
@@ -112,7 +121,6 @@ func (c *Client) QueryMigration() (raw.MigrationInfo, error) {
112121
// Returns nil if migration completed successfully, error otherwise.
113122
func (c *Client) WaitMigration(ctx context.Context, timeout time.Duration) error {
114123
deadline := time.Now().Add(timeout)
115-
pollInterval := 50 * time.Millisecond
116124

117125
for time.Now().Before(deadline) {
118126
select {
@@ -129,7 +137,7 @@ func (c *Client) WaitMigration(ctx context.Context, timeout time.Duration) error
129137
// Check migration status (Status is a pointer in MigrationInfo)
130138
if info.Status == nil {
131139
// Status not available yet, continue polling
132-
time.Sleep(pollInterval)
140+
time.Sleep(qmpMigrationPollInterval)
133141
continue
134142
}
135143

@@ -146,7 +154,7 @@ func (c *Client) WaitMigration(ctx context.Context, timeout time.Duration) error
146154
// Unknown or "none" status - might not have started yet
147155
}
148156

149-
time.Sleep(pollInterval)
157+
time.Sleep(qmpMigrationPollInterval)
150158
}
151159

152160
return fmt.Errorf("migration timeout after %v", timeout)

0 commit comments

Comments
 (0)