aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/internal/testsuite/proc.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-10-06 22:23:20 +0900
committerOphestra <cat@gensokyo.uk>2026-10-06 23:09:19 +0900
commita9e2749f6654d0aa07b274a45c9177d10323f80a (patch)
tree291f5b23a67af036cbe5d374b3d3fb0240fc438c /test/internal/testsuite/proc.go
parent19f36491f2e2a5029ac396c10408d653cad6c81b (diff)
internal/testsuite: move from test
This structure is a lot less clumsy than the old nix-centric layout. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test/internal/testsuite/proc.go')
-rw-r--r--test/internal/testsuite/proc.go353
1 files changed, 0 insertions, 353 deletions
diff --git a/test/internal/testsuite/proc.go b/test/internal/testsuite/proc.go
deleted file mode 100644
index e7ef1aed..00000000
--- a/test/internal/testsuite/proc.go
+++ /dev/null
@@ -1,353 +0,0 @@
-package testsuite
-
-import (
- "bytes"
- "errors"
- "fmt"
- "os"
- "path/filepath"
- "strconv"
- "strings"
- "syscall"
- "unsafe"
-
- "hakurei.app/fhs"
-)
-
-// Stat represents status information read from /proc/pid/stat.
-type Stat struct {
- // The process ID.
- PID int
- // The filename of the executable, with parenthesis stripped.
- Comm string
- // One of the following characters, indicating process state:
- //
- // R Running
- //
- // S Sleeping in an interruptible wait
- //
- // D Waiting in uninterruptible disk sleep
- //
- // Z Zombie
- //
- // T Stopped (on a signal) or (before Linux
- // 2.6.33) trace stopped
- //
- // t Tracing stop (Linux 2.6.33 onward)
- //
- // W Paging (only before Linux 2.6.0)
- //
- // X Dead (from Linux 2.6.0 onward)
- //
- // x Dead (Linux 2.6.33 to 3.13 only)
- //
- // K Wakekill (Linux 2.6.33 to 3.13 only)
- //
- // W Waking (Linux 2.6.33 to 3.13 only)
- //
- // P Parked (Linux 3.9 to 3.13 only)
- //
- // I Idle (Linux 4.14 onward)
- State byte
- // The process ID of the parent of this process.
- PPID int
- // The process group ID of the process.
- PGRP int
- // The session ID of the process.
- Session int
- // The controlling terminal of the process.
- TTYNR int
- // The ID of the foreground process group of the controlling terminal of the
- // process.
- TPGID int
- // The kernel flags word of the process. For bit meanings, see the PF_*
- // defines in the Linux kernel source file include/linux/sched.h.
- Flags uint
- // The number of minor faults the process has made which have not required
- // loading a memory page from disk.
- MinFlt uint
- // The number of minor faults that the process's waited-for children have
- // made.
- CMinFlt uint
- // The number of major faults the process has made which have required
- // loading a memory page from disk.
- MajFlt uint
- // The number of major faults that the process's waited-for children have
- // made.
- CMajFlt uint
- // Amount of time that this process has been scheduled in user mode,
- // measured in clock ticks.
- UTime uint
- // Amount of time that this process has been scheduled in kernel mode,
- // measured in clock ticks.
- STime uint
- // Amount of time that this process's waited-for children have been
- // scheduled in user mode, measured in clock ticks.
- CUTime int
- // Amount of time that this process's waited-for children have been
- // scheduled in kernel mode, measured in clock ticks.
- CSTime int
- // For processes running a real-time scheduling policy, this is the negated
- // scheduling priority, minus one.
- Priority int
- // The nice value, a value in the range 19 (low priority) to -20 (high
- // priority).
- Nice int
- // Number of threads in this process.
- NumThreads int
-
- // unmaintained field: itrealvalue
-
- // The time the process started after system boot. Since Linux 2.6, the
- // value is expressed in clock ticks.
- StartTime uint64
- // Virtual memory size in bytes.
- VSize uint
- // Resident set size in pages.
- RSS int
- // Soft limit in bytes on the rss of the process.
- RSSLim uint64
- // The address above which program text can run.
- StartCode uint64
- // The address below which program text can run.
- EndCode uint64
- // The address of the start (i.e., bottom) of the stack.
- StartStack uint64
- // The current value of ESP (stack pointer), as found in the kernel stack
- // page for the process.
- KSTKESP uint64
- // The current EIP (instruction pointer).
- KSTKEIP uint64
-
- // obsolete fields: signal, blocked, sigignore, sigcatch
-
- // This is the "channel" in which the process is waiting. It is the address
- // of a location in the kernel where the process is sleeping.
- WChan uint64
-
- // unmaintained fields: nswap, cnswap
-
- // Signal to be sent to parent when we die.
- ExitSignal int
- // CPU number last executed on.
- Processor int
- // Real-time scheduling priority, a number in the range 1 to 99 for processes
- // scheduled under a real-time policy, or 0, for non-real-time processes.
- RTPriority uint
- // Scheduling policy (see sched_setscheduler(2)). Decode using the SCHED_*
- // constants in linux/sched.h.
- Policy uint
- // Aggregated block I/O delays, measured in clock ticks (centiseconds).
- DelayAcctBlkIOTicks uint64
- // Guest time of the process (time spent running a virtual CPU for a guest
- // operating system), measured in clock ticks.
- GuestTime int
- // Guest time of the process's children, measured in clock ticks.
- CGuestTime int
-}
-
-// Executable is like [os.Executable], but for the process referred to by s.
-func (s *Stat) Executable() (string, error) {
- path, err := os.Readlink(filepath.Join(fhs.Proc, strconv.Itoa(s.PID), "exe"))
-
- // When the executable has been deleted then Readlink returns a
- // path appended with " (deleted)".
- return strings.TrimSuffix(path, " (deleted)"), err
-}
-
-// Stat populates stat with the proc filesystem entry referred to by s.
-func (s *Stat) Stat(stat *syscall.Stat_t) (err error) {
- err = syscall.Stat(filepath.Join(fhs.Proc, strconv.Itoa(s.PID)), stat)
- if err != nil {
- err = os.NewSyscallError("stat", err)
- }
- return
-}
-
-// Args reads arguments of the process referred to by s.
-func (s *Stat) Args() ([]string, error) {
- p, err := os.ReadFile(filepath.Join(fhs.Proc, strconv.Itoa(s.PID), "cmdline"))
- if err != nil {
- return nil, err
- }
- a := bytes.Split(p, []byte{0})
- if len(a) > 0 && len(a[len(a)-1]) == 0 {
- a = a[:len(a)-1]
- }
-
- args := make([]string, len(a))
- for i, arg := range a {
- args[i] = unsafe.String(unsafe.SliceData(arg), len(arg))
- }
- return args, nil
-}
-
-// ErrBadDelimiters is returned by [Stat.UnmarshalText] if one or both bytes of
-// the comm delimiter pair were missing or misplaced.
-var ErrBadDelimiters = errors.New("missing comm delimiters")
-
-// UnmarshalText populates the structure pointed to by s from text.
-func (s *Stat) UnmarshalText(text []byte) (err error) {
- var (
- discard uint64
- _uint64 = &discard
- _int64 = (*int64)(unsafe.Pointer(&discard))
-
- ld = bytes.Index(text, []byte("("))
- rd = bytes.LastIndex(text, []byte(")"))
- )
-
- if ld <= 0 || rd < 0 {
- return ErrBadDelimiters
- }
-
- if s.PID, err = strconv.Atoi(
- unsafe.String(unsafe.SliceData(text), ld-1),
- ); err != nil {
- return
- }
-
- s.Comm = string(text[ld+1 : rd])
-
- var (
- n int
-
- state string
- )
- n, err = fmt.Fscan(
- bytes.NewBuffer(text[rd+2:]),
- &state,
- &s.PPID,
- &s.PGRP,
- &s.Session,
- &s.TTYNR,
- &s.TPGID,
- &s.Flags,
- &s.MinFlt,
- &s.CMinFlt,
- &s.MajFlt,
- &s.CMajFlt,
- &s.UTime,
- &s.STime,
- &s.CUTime,
- &s.CSTime,
- &s.Priority,
- &s.Nice,
- &s.NumThreads,
- _int64,
- &s.StartTime,
- &s.VSize,
- &s.RSS,
- &s.RSSLim,
- &s.StartCode,
- &s.EndCode,
- &s.StartStack,
- &s.KSTKESP,
- &s.KSTKEIP,
- _uint64,
- _uint64,
- _uint64,
- _uint64,
- &s.WChan,
- _uint64,
- _uint64,
- &s.ExitSignal,
- &s.Processor,
- &s.RTPriority,
- &s.Policy,
- &s.DelayAcctBlkIOTicks,
- &s.GuestTime,
- &s.CGuestTime,
- )
- if err != nil {
- err = fmt.Errorf("field %d: %w", n, err)
- } else if len(state) != 1 {
- err = fmt.Errorf("invalid state %q", state)
- } else {
- s.State = state[0]
- }
- return
-}
-
-// A StatScanner continuously scans the proc filesystem for process status
-// information in /proc/pid/stat.
-type StatScanner struct {
- // Current entry.
- stat Stat
- // Cached top-level /proc entries.
- dents []os.DirEntry
- // Current progress through dents.
- i int
- // Whether the previous call to Scan had repopulated dents.
- wrapped bool
- // First stored error: a non-nil err disables the scanner.
- err error
-}
-
-// IsNotExist returns whether an error is [os.ErrNotExist] or ESRCH.
-func IsNotExist(err error) bool {
- return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ESRCH)
-}
-
-// Scan reads a process status information entry. It returns false if an
-// unrecoverable error is encountered, after which Scan no longer scans new
-// entries.
-func (s *StatScanner) Scan() bool {
- if s.err != nil {
- return false
- }
-
- if s.wrapped = s.i == len(s.dents); s.wrapped {
- if s.dents, s.err = os.ReadDir(fhs.Proc); s.err != nil {
- return false
- }
- s.i = 0
- if len(s.dents) == 0 {
- s.err = syscall.ENOTRECOVERABLE
- return false
- }
- }
-
- for s.i < len(s.dents) {
- dent := s.dents[s.i]
- s.i++
- if !dent.IsDir() {
- continue
- }
-
- pid, err := strconv.Atoi(dent.Name())
- if err != nil {
- continue
- }
-
- var p []byte
- p, err = os.ReadFile(filepath.Join(fhs.Proc, dent.Name(), "stat"))
- if err != nil {
- if IsNotExist(err) {
- continue
- }
- s.err = err
- return false
- }
-
- s.err = s.stat.UnmarshalText(p)
- if s.err == nil && pid != s.stat.PID {
- s.err = fmt.Errorf(
- "bad status information: dent=%d, stat=%d",
- pid, s.stat.PID,
- )
- }
- return s.err == nil
- }
- return s.Scan()
-}
-
-// Stat returns the address of the [Stat] structure populated by the last call
-// to Scan.
-func (s *StatScanner) Stat() *Stat { return &s.stat }
-
-// Err returns the stored error value.
-func (s *StatScanner) Err() error { return s.err }
-
-// Repopulated returns whether the last Scan call had re-read the proc filesystem.
-func (s *StatScanner) Repopulated() bool { return s.wrapped }