Skip to content

Commit

Permalink
gops: concurrently lookup for Go processes
Browse files Browse the repository at this point in the history
  • Loading branch information
rakyll committed Jan 20, 2017
1 parent ad978d7 commit 290a9a1
Showing 1 changed file with 40 additions and 30 deletions.
70 changes: 40 additions & 30 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
package main

import (
"bytes"
"fmt"
"log"
"os"
"strconv"
"strings"
"sync"

"github.com/google/gops/internal/objfile"

ps "github.com/keybase/go-ps"
)

Expand Down Expand Up @@ -72,57 +73,66 @@ func processes() {
if err != nil {
log.Fatal(err)
}
var undetermined int

var wg sync.WaitGroup
wg.Add(len(pss))

for _, pr := range pss {
if pr.Pid() == 0 {
// ignore system process
continue
}
path, err := pr.Path()
if err != nil {
undetermined++
continue
}
ok, agent, err := isGo(pr.Pid(), path)
if err != nil {
// TODO(jbd): worth to report the number?
continue
}
if ok {
fmt.Printf("%d", pr.Pid())
if agent {
fmt.Printf("*")
}
fmt.Printf("\t%v\t(%v)\n", pr.Executable(), path)
}
}
if undetermined > 0 {
fmt.Printf("\n%d processes left undetermined\n", undetermined)
pr := pr
go func() {
defer wg.Done()

printIfGo(pr)
}()
}
wg.Wait()
}

func isGo(pid int, path string) (ok bool, agent bool, err error) {
// reportGo looks up the runtime.buildVersion symbol
// in the process' binary and determines if the process
// if a Go process or not. If the process is a Go process,
// it reports PID, binary name and full path of the binary.
func printIfGo(pr ps.Process) {
if pr.Pid() == 0 {
// ignore system process
return
}
path, err := pr.Path()
if err != nil {
return
}
obj, err := objfile.Open(path)
if err != nil {
return false, false, err
return
}
defer obj.Close()

symbols, err := obj.Symbols()
if err != nil {
return false, false, err
return
}

var ok bool
var agent bool
// TODO(jbd): find a faster way to determine Go programs.
for _, s := range symbols {
if s.Name == "runtime.buildVersion" {
ok = true
}
// TODO(jbd): Stat the pid file to determine if the agent is still working.
if strings.HasPrefix(s.Name, "github.com/google/gops/agent") {
agent = true
}
}
return ok, agent, nil
if ok {
buf := bytes.NewBuffer(nil)
fmt.Fprintf(buf, "%d", pr.Pid())
if agent {
fmt.Fprint(buf, "*")
}
fmt.Fprintf(buf, "\t%v\t(%v)\n", pr.Executable(), path)
buf.WriteTo(os.Stdout)
}
}

func usage(msg string) {
Expand Down

0 comments on commit 290a9a1

Please sign in to comment.