From d4cec92f5690a60b3509ab718bdea72dc520110e Mon Sep 17 00:00:00 2001 From: James O'Doherty Date: Fri, 29 May 2026 20:35:31 -0400 Subject: feat: implement robust namespace lifecycle and resilience suite - Replace marker-file pinning with kernel bind-mount anchors for reliable namespace persistence. - Implement atomic "last-man-out" cleanup sequence using ProfileLock, preventing namespace leaks and race conditions. - Add comprehensive resilience test suite covering: - Crash recovery from stale runtime state. - Host network change stability. - Configuration hot-swap session persistence. - Resource exhaustion and high-churn lifecycle stress. - Align documentation and test expectations with rootless session-based persistence. - Fix argument integrity and isolation leaks. - Ensure 100% pass rate for all E2E and integration tests. --- internal/namespace/lifecycle.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'internal/namespace/lifecycle.go') diff --git a/internal/namespace/lifecycle.go b/internal/namespace/lifecycle.go index 47a804f..99209d5 100644 --- a/internal/namespace/lifecycle.go +++ b/internal/namespace/lifecycle.go @@ -20,6 +20,11 @@ func GetPidsDirPath(pm *paths.PathManager, profile string) string { return pm.ProfilePidsDir(profile) } +// GetControllerPidPath returns the path to the file storing the PID of the tunnel controller. +func GetControllerPidPath(pm *paths.PathManager, profile string) string { + return filepath.Join(pm.RuntimeBaseDir(), "profiles", profile, "controller.pid") +} + // RegisterProcess marks the current process as using the specified profile. func RegisterProcess(pm *paths.PathManager, profile string) error { pidsDir := GetPidsDirPath(pm, profile) @@ -57,6 +62,9 @@ func PruneStalePids(pm *paths.PathManager, profile string) error { } for _, file := range files { + if file.Name() == "controller.pid" { + continue + } pid, err := strconv.Atoi(file.Name()) if err != nil { continue // Ignore non-numeric files @@ -108,3 +116,22 @@ func IsLastProcess(pm *paths.PathManager, profile string) (bool, error) { return activeCount <= 1, nil } + +// SetControllerPid records the current process as the owner of the namespace. +func SetControllerPid(pm *paths.PathManager, profile string) error { + path := GetControllerPidPath(pm, profile) + if err := os.WriteFile(path, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil { + return fmt.Errorf("failed to write controller pid: %w", err) + } + return nil +} + +// GetControllerPid retrieves the PID of the process responsible for cleaning up the namespace. +func GetControllerPid(pm *paths.PathManager, profile string) (int, error) { + path := GetControllerPidPath(pm, profile) + data, err := os.ReadFile(path) + if err != nil { + return 0, err + } + return strconv.Atoi(string(data)) +} -- cgit v1.2.3