]> ruderich.org/simon Gitweb - linux-network-namespace-labs/linux-network-namespace-labs.git/commitdiff
Terminate programs in namespaces before deleting them
authorSimon Ruderich <simon@ruderich.org>
Fri, 1 Nov 2024 08:35:33 +0000 (09:35 +0100)
committerSimon Ruderich <simon@ruderich.org>
Fri, 1 Nov 2024 08:35:33 +0000 (09:35 +0100)
main.go

diff --git a/main.go b/main.go
index 6e3f1e19348fd4b03e1392a8b41f6858a48c74b8..85ddd3b16eec63b5f585ffb1c0cd7b9ce3e2ba00 100644 (file)
--- a/main.go
+++ b/main.go
@@ -15,6 +15,9 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "strconv"
+       "strings"
+       "syscall"
 )
 
 func main() {
@@ -42,6 +45,16 @@ func main() {
                // One namespace per node, named as the node's name
                ns := node.Name
                if netnsExists(ns) {
+                       // Terminate processes in old namespaces
+                       for _, x := range netnsPids(ns) {
+                               log.Printf("  Killing old PID %d", x)
+                               err := syscall.Kill(x, syscall.SIGTERM)
+                               if err != nil {
+                                       log.Fatalf("failed to kill %d: %v", x, err)
+                               }
+                               // Also try SIGHUP to terminate shells which ignore SIGTERM
+                               _ = syscall.Kill(x, syscall.SIGHUP)
+                       }
                        // Prevent any conflicts with existing data
                        ip("netns", "del", ns)
                        // Don't remove anything in /etc/netns/ as the user might store
@@ -135,6 +148,30 @@ func netnsExists(name string) bool {
        return true
 }
 
+func netnsPids(netns string) []int {
+       args := []string{"netns", "pids", netns}
+       xargs := append([]string{"ip"}, args...)
+
+       cmd := exec.Command("ip", args...)
+       out, err := cmd.Output()
+       if err != nil {
+               log.Fatalf("failed to run %q: %v", xargs, err)
+       }
+
+       var res []int
+       xs := strings.FieldsFunc(string(out), func(c rune) bool {
+               return c == '\n'
+       })
+       for _, x := range xs {
+               y, err := strconv.Atoi(x)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               res = append(res, y)
+       }
+       return res
+}
+
 func ifaceExists(netns, name string) bool {
        args := []string{"-n", netns, "-json", "link"}
        xargs := append([]string{"ip"}, args...)