Skip to content

Commit 63279af

Browse files
committed
Refactor supervisor management to start after container creation and pass overlay root via environment variable
1 parent ffde723 commit 63279af

4 files changed

Lines changed: 45 additions & 14 deletions

File tree

cmd/vminitd/main.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818

1919
"github.com/spin-stack/spinbox/internal/guest/vminit/config"
2020
"github.com/spin-stack/spinbox/internal/guest/vminit/service"
21-
"github.com/spin-stack/spinbox/internal/guest/vminit/supervisor"
2221
"github.com/spin-stack/spinbox/internal/guest/vminit/system"
2322
"github.com/spin-stack/spinbox/internal/guest/vminit/systools"
2423

@@ -108,18 +107,9 @@ func run(ctx context.Context, cfg *config.ServiceConfig) error {
108107

109108
log.G(ctx).WithField("t", time.Since(t1)).Debug("initialized vminitd")
110109

111-
// Start supervisor agent in background with automatic restart on crash.
112-
// The supervisor binary is injected via extras disk and will be available
113-
// at /var/lib/spin-stack/bin/spin-supervisor after VM boot.
114-
// RunWithMonitoring blocks until context is cancelled, handling all restarts.
115-
go func() {
116-
// Wait a bit for extras disk to be mounted and files extracted
117-
time.Sleep(2 * time.Second)
118-
119-
if err := supervisor.RunWithMonitoring(ctx); err != nil {
120-
log.G(ctx).WithError(err).Error("supervisor monitor exited with error")
121-
}
122-
}()
110+
// Note: The supervisor agent is now started after container creation
111+
// (in runc/container.go) with the overlay root path passed via env var.
112+
// This ensures the supervisor has access to the container's rootfs.
123113

124114
// Limit GOMAXPROCS for VM environment to prevent scheduler overhead
125115
// Cap at maxGOMAXPROCS to improve cache locality, but respect available CPUs

internal/guest/vminit/runc/container.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
spinbox "github.com/spin-stack/spinbox/api/types/spinbox/v1"
2222
"github.com/spin-stack/spinbox/internal/guest/vminit/process"
2323
"github.com/spin-stack/spinbox/internal/guest/vminit/stream"
24+
"github.com/spin-stack/spinbox/internal/guest/vminit/supervisor"
2425
"github.com/spin-stack/spinbox/internal/host/mountutil"
2526
)
2627

@@ -132,6 +133,11 @@ func NewContainer(ctx context.Context, platform stdio.Platform, r *task.CreateTa
132133
return nil, err
133134
}
134135
log.G(ctx).WithField("rootfs", rootfs).Info("rootfs components mounted")
136+
137+
// Start the supervisor agent now that the rootfs is available.
138+
// Pass the rootfs path via environment variable so the supervisor
139+
// knows where to find files generated by the container.
140+
go supervisor.StartWithOverlayRoot(ctx, rootfs)
135141
}
136142

137143
// Relax OCI spec restrictions - VM provides the security boundary

internal/guest/vminit/supervisor/monitor.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const (
3434
// Monitor manages the supervisor process lifecycle with automatic restart.
3535
type Monitor struct {
3636
binaryPath string
37+
extraEnv []string // Additional environment variables to pass to supervisor
3738

3839
mu sync.Mutex
3940
cmd *exec.Cmd
@@ -52,6 +53,12 @@ func NewMonitor(binaryPath string) *Monitor {
5253
}
5354
}
5455

56+
// SetExtraEnv sets additional environment variables to pass to the supervisor process.
57+
// These are appended to the current process environment on each start.
58+
func (m *Monitor) SetExtraEnv(env []string) {
59+
m.extraEnv = env
60+
}
61+
5562
// Run starts the supervisor and monitors it for crashes.
5663
// It blocks until the context is cancelled or max restarts is exceeded.
5764
func (m *Monitor) Run(ctx context.Context) error {
@@ -144,7 +151,7 @@ func (m *Monitor) start(ctx context.Context) error {
144151
cmd := exec.Command(m.binaryPath) //nolint:gosec
145152
cmd.Stdout = os.Stdout
146153
cmd.Stderr = os.Stderr
147-
cmd.Env = os.Environ()
154+
cmd.Env = append(os.Environ(), m.extraEnv...)
148155
cmd.SysProcAttr = &syscall.SysProcAttr{
149156
Setsid: true, // Create new session
150157
}

internal/guest/vminit/supervisor/supervisor.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ const (
3030

3131
// LogFile is where supervisor logs are written.
3232
LogFile = "/var/log/spin-supervisor.log"
33+
34+
// OverlayRootEnvVar is the environment variable name used to pass
35+
// the overlay filesystem root path to the supervisor.
36+
OverlayRootEnvVar = "SPINBOX_OVERLAY_ROOT"
3337
)
3438

3539
// findBinary searches for the supervisor binary.
@@ -82,6 +86,29 @@ func findBinary(ctx context.Context) string {
8286
//
8387
// Returns nil immediately if supervisor binary is not found.
8488
func RunWithMonitoring(ctx context.Context) error {
89+
return runWithEnv(ctx, nil)
90+
}
91+
92+
// StartWithOverlayRoot starts the supervisor agent with the overlay root path
93+
// passed via environment variable. This should be called after the container's
94+
// rootfs is mounted so the supervisor can access files in the overlay.
95+
//
96+
// The overlayRoot parameter is the path to the container's mounted rootfs,
97+
// which will be passed to the supervisor via SPINBOX_OVERLAY_ROOT env var.
98+
//
99+
// This function runs in a goroutine and does not block.
100+
func StartWithOverlayRoot(ctx context.Context, overlayRoot string) {
101+
env := []string{OverlayRootEnvVar + "=" + overlayRoot}
102+
103+
log.G(ctx).WithField("overlay_root", overlayRoot).Info("starting supervisor with overlay root")
104+
105+
if err := runWithEnv(ctx, env); err != nil {
106+
log.G(ctx).WithError(err).Error("supervisor monitor exited with error")
107+
}
108+
}
109+
110+
// runWithEnv starts the supervisor with optional additional environment variables.
111+
func runWithEnv(ctx context.Context, extraEnv []string) error {
85112
binaryPath := findBinary(ctx)
86113
if binaryPath == "" {
87114
log.G(ctx).Info("supervisor binary not found, skipping")
@@ -90,5 +117,6 @@ func RunWithMonitoring(ctx context.Context) error {
90117

91118
log.G(ctx).WithField("path", binaryPath).Info("starting supervisor with monitoring")
92119
monitor := NewMonitor(binaryPath)
120+
monitor.SetExtraEnv(extraEnv)
93121
return monitor.Run(ctx)
94122
}

0 commit comments

Comments
 (0)