1
0
forked from wrenn/wrenn

fix: assorted bug fixes for CH migration

Fix resource leaks, race conditions, and error handling across host
agent and control plane: proper sparse file cleanup on close error,
connect error wrapping for MakeDir, CoW file cleanup on pause failure,
per-sandbox VM directories, deferred map deletion to avoid race in VM
destroy, and goroutine launch for extension background workers.
This commit is contained in:
2026-05-17 01:47:56 +06:00
parent fb16bc9ed1
commit a5425969ed
6 changed files with 17 additions and 5 deletions

View File

@ -379,5 +379,9 @@ func createSparseFile(path string, sizeBytes int64) error {
os.Remove(path) os.Remove(path)
return err return err
} }
return f.Close() if err := f.Close(); err != nil {
os.Remove(path)
return err
}
return nil
} }

View File

@ -301,7 +301,7 @@ func (s *Server) MakeDir(
resp, err := client.MakeDir(ctx, msg.Path) resp, err := client.MakeDir(ctx, msg.Path)
if err != nil { if err != nil {
return nil, fmt.Errorf("make dir: %w", err) return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("make dir: %w", err))
} }
return connect.NewResponse(&pb.MakeDirResponse{ return connect.NewResponse(&pb.MakeDirResponse{
@ -373,6 +373,8 @@ func (s *Server) ExecStream(
Error: ev.Error, Error: ev.Error,
}, },
} }
default:
continue
} }
if err := stream.Send(&resp); err != nil { if err := stream.Send(&resp); err != nil {
return err return err
@ -889,6 +891,8 @@ func (s *Server) ConnectProcess(
Error: ev.Error, Error: ev.Error,
}, },
} }
default:
continue
} }
if err := stream.Send(&resp); err != nil { if err := stream.Send(&resp); err != nil {
return err return err

View File

@ -541,6 +541,7 @@ func (m *Manager) Pause(ctx context.Context, sandboxID string) error {
warnErr("snapshot dir cleanup error", sandboxID, os.RemoveAll(pauseDir)) warnErr("snapshot dir cleanup error", sandboxID, os.RemoveAll(pauseDir))
warnErr("network cleanup error during pause", sandboxID, network.RemoveNetwork(sb.slot)) warnErr("network cleanup error during pause", sandboxID, network.RemoveNetwork(sb.slot))
m.slots.Release(sb.SlotIndex) m.slots.Release(sb.SlotIndex)
os.Remove(sb.dmDevice.CowPath)
if sb.baseImagePath != "" { if sb.baseImagePath != "" {
m.loops.Release(sb.baseImagePath) m.loops.Release(sb.baseImagePath)
} }

View File

@ -77,7 +77,7 @@ func (c *VMConfig) applyDefaults() {
c.SocketPath = fmt.Sprintf("/tmp/ch-%s.sock", c.SandboxID) c.SocketPath = fmt.Sprintf("/tmp/ch-%s.sock", c.SandboxID)
} }
if c.SandboxDir == "" { if c.SandboxDir == "" {
c.SandboxDir = "/tmp/ch-vm" c.SandboxDir = fmt.Sprintf("/tmp/ch-vm-%s", c.SandboxID)
} }
if c.TapDevice == "" { if c.TapDevice == "" {
c.TapDevice = "tap0" c.TapDevice = "tap0"

View File

@ -143,7 +143,6 @@ func (m *Manager) Destroy(ctx context.Context, sandboxID string) error {
m.mu.Unlock() m.mu.Unlock()
return fmt.Errorf("VM not found: %s", sandboxID) return fmt.Errorf("VM not found: %s", sandboxID)
} }
delete(m.vms, sandboxID)
m.mu.Unlock() m.mu.Unlock()
slog.Info("destroying VM", "sandbox", sandboxID) slog.Info("destroying VM", "sandbox", sandboxID)
@ -161,6 +160,10 @@ func (m *Manager) Destroy(ctx context.Context, sandboxID string) error {
os.Remove(vm.Config.SocketPath) os.Remove(vm.Config.SocketPath)
m.mu.Lock()
delete(m.vms, sandboxID)
m.mu.Unlock()
slog.Info("VM destroyed", "sandbox", sandboxID) slog.Info("VM destroyed", "sandbox", sandboxID)
return nil return nil
} }

View File

@ -255,7 +255,7 @@ func Run(opts ...Option) {
// Start extension background workers. // Start extension background workers.
for _, ext := range o.extensions { for _, ext := range o.extensions {
for _, worker := range ext.BackgroundWorkers(sctx) { for _, worker := range ext.BackgroundWorkers(sctx) {
worker(ctx) go worker(ctx)
} }
} }