From 547679f88eeefdae2ce62434e2190157aff70587 Mon Sep 17 00:00:00 2001 From: Lomanic Date: Fri, 6 Sep 2019 13:36:22 +0200 Subject: [PATCH] [process] Fix #760 implement IsRunning by checking process with same PID has same CreateTime as current process --- process/process.go | 37 +++++++++++++++++++++++++++++++++++++ process/process_darwin.go | 12 +----------- process/process_fallback.go | 11 +---------- process/process_freebsd.go | 12 +----------- process/process_linux.go | 17 +---------------- process/process_openbsd.go | 13 +------------ process/process_test.go | 27 +++++++++++++++++++++++++++ process/process_windows.go | 14 +------------- 8 files changed, 70 insertions(+), 73 deletions(-) diff --git a/process/process.go b/process/process.go index c674b3d..87b647b 100644 --- a/process/process.go +++ b/process/process.go @@ -31,6 +31,7 @@ type Process struct { numThreads int32 memInfo *MemoryInfoStat sigInfo *SignalInfoStat + createTime int64 lastCPUTimes *cpu.TimesStat lastCPUTime time.Time @@ -163,6 +164,7 @@ func NewProcess(pid int32) (*Process, error) { if !exists { return p, ErrorProcessNotRunning } + go p.CreateTime() return p, nil } @@ -222,6 +224,41 @@ func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration return ret, nil } +// IsRunning returns whether the process is still running or not. +func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { + createTime, err := p.CreateTimeWithContext(ctx) + if err != nil { + return false, err + } + p2, err := NewProcess(p.Pid) + if err == ErrorProcessNotRunning { + return false, nil + } + createTime2, err := p2.CreateTimeWithContext(ctx) + if err != nil { + return false, err + } + return createTime == createTime2, nil +} + +// CreateTime returns created time of the process in milliseconds since the epoch, in UTC. +func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { + if p.createTime != 0 { + return p.createTime, nil + } + createTime, err := p.createTimeWithContext(ctx) + p.createTime = createTime + return p.createTime, err +} + func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 { if delta == 0 { return 0 diff --git a/process/process_darwin.go b/process/process_darwin.go index 480c236..198cce2 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -129,11 +129,8 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) } return r[0], err } -func (p *Process) CreateTime() (int64, error) { - return p.CreateTimeWithContext(context.Background()) -} -func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { +func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { r, err := callPsWithContext(ctx, "etime", p.Pid, false) if err != nil { return 0, err @@ -527,13 +524,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([] return nil, common.ErrNotImplementedError } -func (p *Process) IsRunning() (bool, error) { - return p.IsRunningWithContext(context.Background()) -} - -func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { - return true, common.ErrNotImplementedError -} func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return p.MemoryMapsWithContext(context.Background(), grouped) } diff --git a/process/process_fallback.go b/process/process_fallback.go index 3201efd..1cb55c8 100644 --- a/process/process_fallback.go +++ b/process/process_fallback.go @@ -93,11 +93,8 @@ func (p *Process) CmdlineSlice() ([]string, error) { func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { return []string{}, common.ErrNotImplementedError } -func (p *Process) CreateTime() (int64, error) { - return p.CreateTimeWithContext(context.Background()) -} -func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { +func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { @@ -283,13 +280,7 @@ func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { return []net.IOCountersStat{}, common.ErrNotImplementedError } -func (p *Process) IsRunning() (bool, error) { - return p.IsRunningWithContext(context.Background()) -} -func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { - return true, common.ErrNotImplementedError -} func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return p.MemoryMapsWithContext(context.Background(), grouped) } diff --git a/process/process_freebsd.go b/process/process_freebsd.go index 0d4bbfc..3da66b5 100644 --- a/process/process_freebsd.go +++ b/process/process_freebsd.go @@ -116,11 +116,8 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) return strParts, nil } -func (p *Process) CreateTime() (int64, error) { - return p.CreateTimeWithContext(context.Background()) -} -func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { +func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { @@ -428,13 +425,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([] return nil, common.ErrNotImplementedError } -func (p *Process) IsRunning() (bool, error) { - return p.IsRunningWithContext(context.Background()) -} - -func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { - return true, common.ErrNotImplementedError -} func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return p.MemoryMapsWithContext(context.Background(), grouped) } diff --git a/process/process_linux.go b/process/process_linux.go index 8c0649d..fab7b55 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -130,12 +130,7 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) return p.fillSliceFromCmdlineWithContext(ctx) } -// CreateTime returns created time of the process in milliseconds since the epoch, in UTC. -func (p *Process) CreateTime() (int64, error) { - return p.CreateTimeWithContext(context.Background()) -} - -func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { +func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { _, _, _, createTime, _, _, _, err := p.fillFromStatWithContext(ctx) if err != nil { return 0, err @@ -550,16 +545,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([] return net.IOCountersByFile(pernic, filename) } -// IsRunning returns whether the process is running or not. -// Not implemented yet. -func (p *Process) IsRunning() (bool, error) { - return p.IsRunningWithContext(context.Background()) -} - -func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { - return true, common.ErrNotImplementedError -} - // MemoryMaps get memory maps from /proc/(pid)/smaps func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return p.MemoryMapsWithContext(context.Background(), grouped) diff --git a/process/process_openbsd.go b/process/process_openbsd.go index 56e3500..8bac098 100644 --- a/process/process_openbsd.go +++ b/process/process_openbsd.go @@ -114,11 +114,7 @@ func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { return strings.Join(argv, " "), nil } -func (p *Process) CreateTime() (int64, error) { - return p.CreateTimeWithContext(context.Background()) -} - -func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { +func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { @@ -415,13 +411,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([] return nil, common.ErrNotImplementedError } -func (p *Process) IsRunning() (bool, error) { - return p.IsRunningWithContext(context.Background()) -} - -func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { - return true, common.ErrNotImplementedError -} func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return p.MemoryMapsWithContext(context.Background(), grouped) } diff --git a/process/process_test.go b/process/process_test.go index f109c0f..ffa8257 100644 --- a/process/process_test.go +++ b/process/process_test.go @@ -539,3 +539,30 @@ func Test_Kill(t *testing.T) { assert.Nil(t, err) cmd.Wait() } + +func Test_IsRunning(t *testing.T) { + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + cmd = exec.Command("ping", "localhost", "-n", "2") + } else { + cmd = exec.Command("sleep", "1") + } + cmd.Start() + p, err := NewProcess(int32(cmd.Process.Pid)) + assert.Nil(t, err) + running, err := p.IsRunning() + if err != nil { + t.Fatalf("IsRunning error: %v", err) + } + if !running { + t.Fatalf("process should be found running") + } + cmd.Wait() + running, err = p.IsRunning() + if err != nil { + t.Fatalf("IsRunning error: %v", err) + } + if running { + t.Fatalf("process should NOT be found running") + } +} diff --git a/process/process_windows.go b/process/process_windows.go index 283c3ec..d42b34f 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -320,11 +320,7 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) return strings.Split(cmdline, " "), nil } -func (p *Process) CreateTime() (int64, error) { - return p.CreateTimeWithContext(context.Background()) -} - -func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { +func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { ru, err := getRusage(p.Pid) if err != nil { return 0, fmt.Errorf("could not get CreationDate: %s", err) @@ -659,14 +655,6 @@ func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([] return nil, common.ErrNotImplementedError } -func (p *Process) IsRunning() (bool, error) { - return p.IsRunningWithContext(context.Background()) -} - -func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { - return true, common.ErrNotImplementedError -} - func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { return p.MemoryMapsWithContext(context.Background(), grouped) }