From b79fc398c618e460956cd7fb76649f4c8218fc9f Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 3 Jul 2026 13:19:23 +0200 Subject: [PATCH] Add Process.Refresh Add a method to reload all data associated with a process from the OS. --- process.go | 10 ++++++++++ process_test.go | 11 +++++++++++ process_unix.go | 17 +++++++++++++++++ process_windows.go | 14 ++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/process.go b/process.go index 2bb20fb..d22a00a 100644 --- a/process.go +++ b/process.go @@ -12,28 +12,38 @@ import "time" type Process interface { // PID returns the process ID for this process. PID() int + // PPID returns the parent process ID for this process. PPID() int + // UID returns the numeric user ID for this process. On Windows, it // always returns -1. UID() int + // GID returns the numeric group ID for this process. On Windows, it // always returns -1. GID() int + // ExecutablePath returns the full path to the executable of this // process. This information might not be available on all platforms or // if the executable was removed while the process was still running. ExecutablePath() string + // ExecutableArgs returns the command line arguments for this process, // including the executable name. This information might not be // available on all platforms. ExecutableArgs() []string + // Command returns the command or executable name running this process. // On some platforms (e.g. macOS and the BSDs) this name might be // truncated. Command() string + // CreationTime returns the creation time for this process. CreationTime() time.Time + + // Refresh reloads all data associated with this process from the OS. + Refresh() error } // Processes returns all currently running processes. diff --git a/process_test.go b/process_test.go index 02d5c25..1501636 100644 --- a/process_test.go +++ b/process_test.go @@ -195,6 +195,17 @@ func TestFindProcessInit(t *testing.T) { } } +func TestProcessRefresh(t *testing.T) { + proc, err := ps.FindProcess(os.Getpid()) + if err != nil { + t.Fatalf("FindProcess: %v", err) + } + + checkOwnProcess(t, proc) + proc.Refresh() + checkOwnProcess(t, proc) +} + func BenchmarkProcesses(b *testing.B) { b.ReportAllocs() for b.Loop() { diff --git a/process_unix.go b/process_unix.go index a09426b..0227016 100644 --- a/process_unix.go +++ b/process_unix.go @@ -7,6 +7,7 @@ package ps import ( + "fmt" "path/filepath" "time" ) @@ -59,3 +60,19 @@ func (p *unixProcess) ExecutableArgs() []string { func (p *unixProcess) CreationTime() time.Time { return p.creationTime } + +func (p *unixProcess) Refresh() error { + proc, err := findProcess(p.pid) + if err != nil { + return fmt.Errorf("failed to refresh process: %w", err) + } + np := proc.(*unixProcess) + p.ppid = np.ppid + p.uid = np.uid + p.gid = np.gid + p.command = np.command + p.executablePath = np.executablePath + p.executableArgs = np.executableArgs + p.creationTime = np.creationTime + return nil +} diff --git a/process_windows.go b/process_windows.go index 6f888c4..36b0e5b 100644 --- a/process_windows.go +++ b/process_windows.go @@ -56,6 +56,20 @@ func (p *windowsProcess) CreationTime() time.Time { return p.creationTime } +func (p *windowsProcess) Refresh() error { + proc, err := findProcess(p.pid) + if err != nil { + return err + } + np := proc.(*windowsProcess) + p.ppid = np.ppid + p.command = np.command + p.executablePath = np.executablePath + p.executableArgs = np.executableArgs + p.creationTime = np.creationTime + return nil +} + func getCreationTime(pid uint32) time.Time { c, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid) if err != nil {