diff --git a/process/process_darwin.go b/process/process_darwin.go index d4c0e2e..5b1f1bd 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -4,6 +4,7 @@ package process import ( "bytes" + "fmt" "strconv" "strings" "syscall" @@ -92,7 +93,18 @@ func (p *Process) Cwd() (string, error) { return "", common.NotImplementedError } func (p *Process) Parent() (*Process, error) { - return p, common.NotImplementedError + r, err := callLsof("R", p.Pid) + if err != nil { + return nil, err + } + if len(r) != 1 { // TODO: pid 1 + return nil, fmt.Errorf("wrong number of parents") + } + v, err := strconv.Atoi(r[0]) + if err != nil { + return nil, err + } + return NewProcess(int32(v)) } func (p *Process) Status() (string, error) { r, err := callPs("state", p.Pid, false) @@ -166,15 +178,6 @@ func (p *Process) NumFDs() (int32, error) { return 0, common.NotImplementedError } func (p *Process) NumThreads() (int32, error) { - /* - k, err := p.getKProc() - if err != nil { - return 0, err - } - - return k.KiNumthreads, nil - */ - r, err := callPs("utime,stime", p.Pid, true) if err != nil { return 0, err @@ -412,3 +415,26 @@ func callPs(arg string, pid int32, threadOption bool) ([][]string, error) { return ret, nil } + +func callLsof(arg string, pid int32) ([]string, error) { + var cmd []string + if pid == 0 { // will get from all processes. + cmd = []string{"-F" + arg} + } else { + cmd = []string{"-a", "-F" + arg, "-p", strconv.Itoa(int(pid))} + } + out, err := invoke.Command("/usr/sbin/lsof", cmd...) + if err != nil { + return []string{}, err + } + lines := strings.Split(string(out), "\n") + + var ret []string + for _, l := range lines[1:] { + if strings.HasPrefix(l, arg) { + ret = append(ret, l[1:]) // delete first char + } + } + + return ret, nil +} diff --git a/process/process_linux.go b/process/process_linux.go index 9c145e6..79039bf 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -4,6 +4,7 @@ package process import ( "encoding/json" + "fmt" "io/ioutil" "os" "path/filepath" @@ -11,10 +12,10 @@ import ( "strings" "syscall" - common "github.com/shirou/gopsutil/common" - cpu "github.com/shirou/gopsutil/cpu" - host "github.com/shirou/gopsutil/host" - net "github.com/shirou/gopsutil/net" + "github.com/shirou/gopsutil/common" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/net" ) const ( @@ -94,7 +95,18 @@ func (p *Process) Cwd() (string, error) { return p.fillFromCwd() } func (p *Process) Parent() (*Process, error) { - return nil, common.NotImplementedError + r, err := callLsof("R", p.Pid) + if err != nil { + return nil, err + } + if len(r) != 1 { // TODO: pid 1 + return nil, fmt.Errorf("wrong number of parents") + } + v, err := strconv.Atoi(r[0]) + if err != nil { + return nil, err + } + return NewProcess(int32(v)) } func (p *Process) Status() (string, error) { err := p.fillFromStatus() @@ -619,3 +631,26 @@ func Pids() ([]int32, error) { return ret, nil } + +func callLsof(arg string, pid int32) ([]string, error) { + var cmd []string + if pid == 0 { // will get from all processes. + cmd = []string{"-F" + arg} + } else { + cmd = []string{"-a", "-F" + arg, "-p", strconv.Itoa(int(pid))} + } + out, err := invoke.Command("/usr/bin/lsof", cmd...) + if err != nil { + return []string{}, err + } + lines := strings.Split(string(out), "\n") + + var ret []string + for _, l := range lines[1:] { + if strings.HasPrefix(l, arg) { + ret = append(ret, l[1:]) // delete first char + } + } + + return ret, nil +} diff --git a/process/process_test.go b/process/process_test.go index 84d311b..2d2c9c5 100644 --- a/process/process_test.go +++ b/process/process_test.go @@ -1,7 +1,6 @@ package process import ( - "fmt" "os" "runtime" "strings" @@ -38,7 +37,7 @@ func Test_Pids_Fail(t *testing.T) { mu.Lock() defer mu.Unlock() - invoke = common.FakeInvoke{Suffix: "fail", Error: fmt.Errorf("hoge")} + invoke = common.FakeInvoke{Suffix: "fail"} ret, err := Pids() invoke = common.Invoke{} if err != nil { @@ -48,7 +47,6 @@ func Test_Pids_Fail(t *testing.T) { t.Errorf("wrong getted pid nums: %v/%d", ret, len(ret)) } } - func Test_Pid_exists(t *testing.T) { checkPid := os.Getpid() @@ -276,3 +274,18 @@ func Test_Process_CreateTime(t *testing.T) { t.Errorf("process created time is wrong.") } } + +func Test_Parent(t *testing.T) { + p := testGetProcess() + + c, err := p.Parent() + if err != nil { + t.Errorf("error %v", err) + } + if c == nil { + t.Errorf("could not get parent") + } + if c.Pid == 0 { + t.Errorf("wrong parent pid") + } +}