| 1 | //go:build linux |
| 2 | |
| 3 | package host |
| 4 | |
| 5 | import ( |
| 6 | "errors" |
| 7 | "os" |
| 8 | "path/filepath" |
| 9 | "strconv" |
| 10 | "strings" |
| 11 | "testing" |
| 12 | |
| 13 | "github.com/carlosframework/platform/internal/hostbox" |
| 14 | ) |
| 15 | |
| 16 | // journal-migrate holds the registry through a child it runs as the service |
| 17 | // user. The quiesce scan must not count that child (or any other direct |
| 18 | // child of the migration) as a running service process, or the migration |
| 19 | // refuses itself every time; any other service-user process still refuses. |
| 20 | func TestQuiesceScanSkipsOwnChildren(t *testing.T) { |
| 21 | uid := os.Getuid() |
| 22 | self := 4242 |
| 23 | proc := t.TempDir() |
| 24 | mk := func(pid, ppid int) { |
| 25 | dir := filepath.Join(proc, strconv.Itoa(pid)) |
| 26 | if err := os.Mkdir(dir, 0o755); err != nil { |
| 27 | t.Fatal(err) |
| 28 | } |
| 29 | // /proc/<pid>/stat: "pid (comm) state ppid ..." |
| 30 | stat := strconv.Itoa(pid) + " (carlos x) S " + strconv.Itoa(ppid) + " 1 1 0\n" |
| 31 | if err := os.WriteFile(filepath.Join(dir, "stat"), []byte(stat), 0o644); err != nil { |
| 32 | t.Fatal(err) |
| 33 | } |
| 34 | } |
| 35 | mk(5000, self) // the registry child |
| 36 | if err := scanQuiesceProcs(proc, uid, self); err != nil { |
| 37 | t.Fatalf("own child refused: %v", err) |
| 38 | } |
| 39 | mk(5001, 1) // any other service-user process |
| 40 | err := scanQuiesceProcs(proc, uid, self) |
| 41 | if !errors.Is(err, hostbox.ErrTypedJournal) || !strings.Contains(err.Error(), "5001") { |
| 42 | t.Fatalf("foreign process not refused by pid: %v", err) |
| 43 | } |
| 44 | } |
| 45 | |