Skip to content

Commit

Permalink
Merge pull request #109 from coroot/fix_python_instrumentation
Browse files Browse the repository at this point in the history
python: search for `pthread_cond_timedwait` in both libc.so and libpthread.so
  • Loading branch information
def authored Jul 15, 2024
2 parents 163e1f1 + 4c54df0 commit d135225
Showing 1 changed file with 38 additions and 36 deletions.
74 changes: 38 additions & 36 deletions ebpftracer/python.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/cilium/ebpf/link"
"github.com/coroot/coroot-node-agent/proc"
"golang.org/x/exp/maps"
"k8s.io/klog/v2"
)

Expand All @@ -17,68 +18,69 @@ var (
)

func (t *Tracer) AttachPythonThreadLockProbes(pid uint32) []link.Link {
exePath := getPthreadLib(pid)
if exePath == "" {
return nil
}

log := func(msg string, err error) {
log := func(libPath, msg string, err error) {
if err != nil {
for _, s := range []string{"no such file or directory", "no such process", "permission denied"} {
if strings.HasSuffix(err.Error(), s) {
return
}
}
klog.ErrorfDepth(1, "pid=%d lib=%s: %s: %s", pid, exePath, msg, err)
klog.ErrorfDepth(1, "pid=%d lib=%s: %s: %s", pid, libPath, msg, err)
return
}
klog.InfofDepth(1, "pid=%d lib=%s: %s", pid, exePath, msg)
}
exe, err := link.OpenExecutable(exePath)
if err != nil {
log("failed to open executable", err)
return nil
klog.InfofDepth(1, "pid=%d lib=%s: %s", pid, libPath, msg)
}
var links []link.Link
uprobe, err := exe.Uprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_enter"], nil)
if err != nil {
log("failed to attach uprobe", err)
return nil

var (
lastErr error
links []link.Link
libPath string
)

for _, libPath = range getPthreadLibs(pid) {
exe, err := link.OpenExecutable(libPath)
if err != nil {
log(libPath, "failed to open executable", err)
return nil
}
var uprobe, uretprobe link.Link
uprobe, lastErr = exe.Uprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_enter"], nil)
if lastErr != nil {
continue
}
links = append(links, uprobe)
uretprobe, lastErr = exe.Uretprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_exit"], nil)
if lastErr != nil {
continue
}
links = append(links, uretprobe)
log(libPath, "python uprobes attached", nil)
break
}
links = append(links, uprobe)
uretprobe, err := exe.Uretprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_exit"], nil)
if err != nil {
log("failed to attach uretprobe", err)
return nil
if lastErr != nil {
log(libPath, "failed to attach uprobe", lastErr)
}
links = append(links, uretprobe)
log("python uprobes attached", nil)
return links
}

func getPthreadLib(pid uint32) string {
func getPthreadLibs(pid uint32) []string {
f, err := os.Open(proc.Path(pid, "maps"))
if err != nil {
return ""
return nil
}
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Split(bufio.ScanLines)
libc := ""
libs := map[string]bool{}
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
if len(parts) <= 5 {
continue
}
libPath := parts[5]
switch {
case libcRegexp.MatchString(libPath):
libc = proc.Path(pid, "root", libPath)
case muslRegexp.MatchString(libPath):
return proc.Path(pid, "root", libPath)
case strings.Contains(libPath, "libpthread"):
return proc.Path(pid, "root", libPath)
if libcRegexp.MatchString(libPath) || muslRegexp.MatchString(libPath) || strings.Contains(libPath, "libpthread") {
libs[proc.Path(pid, "root", libPath)] = true
}
}
return libc
return maps.Keys(libs)
}

0 comments on commit d135225

Please sign in to comment.