|
5 | 5 | "fmt" |
6 | 6 | "os" |
7 | 7 | "path/filepath" |
| 8 | + "sync/atomic" |
8 | 9 | "time" |
9 | 10 |
|
10 | 11 | "github.com/faize-ai/faize/internal/changeset" |
@@ -269,6 +270,17 @@ func runStart(cmd *cobra.Command, args []string) error { |
269 | 270 | } |
270 | 271 | Debug("VM started successfully") |
271 | 272 |
|
| 273 | + // Timeout enforcement: stop the VM when the timeout expires |
| 274 | + var timedOut atomic.Bool |
| 275 | + if timeoutDuration > 0 { |
| 276 | + timer := time.AfterFunc(timeoutDuration, func() { |
| 277 | + timedOut.Store(true) |
| 278 | + fmt.Printf("\nSession timeout (%s) reached. Stopping...\n", timeoutDuration) |
| 279 | + _ = manager.Stop(sess.ID) |
| 280 | + }) |
| 281 | + defer timer.Stop() |
| 282 | + } |
| 283 | + |
272 | 284 | // Take pre-snapshots of rw mounts for change tracking |
273 | 285 | type mountSnapshot struct { |
274 | 286 | source string |
@@ -312,8 +324,28 @@ func runStart(cmd *cobra.Command, args []string) error { |
312 | 324 |
|
313 | 325 | // Attach to console — session stops when we return |
314 | 326 | fmt.Println("Attaching to console... (~. to detach)") |
315 | | - if err := manager.Attach(sess.ID); err != nil && !errors.Is(err, vm.ErrUserDetach) { |
316 | | - return fmt.Errorf("console error: %w", err) |
| 327 | + attachErr := manager.Attach(sess.ID) |
| 328 | + if attachErr != nil && !errors.Is(attachErr, vm.ErrUserDetach) { |
| 329 | + return fmt.Errorf("console error: %w", attachErr) |
| 330 | + } |
| 331 | + |
| 332 | + // Determine exit reason and persist session metadata |
| 333 | + exitReason := "normal" |
| 334 | + if timedOut.Load() { |
| 335 | + exitReason = "timeout" |
| 336 | + } else if errors.Is(attachErr, vm.ErrUserDetach) { |
| 337 | + exitReason = "detach" |
| 338 | + } |
| 339 | + now := time.Now() |
| 340 | + sess.Timeout = startTimeout |
| 341 | + sess.StoppedAt = &now |
| 342 | + sess.ExitReason = exitReason |
| 343 | + sess.Status = "stopped" |
| 344 | + store, storeErr := session.NewStore() |
| 345 | + if storeErr == nil { |
| 346 | + if saveErr := store.Save(sess); saveErr != nil { |
| 347 | + Debug("Failed to save session: %v", saveErr) |
| 348 | + } |
317 | 349 | } |
318 | 350 |
|
319 | 351 | // Post-session change tracking |
|
0 commit comments