Fix tools still referencing ProcUtils (#625)
authorTeng Qin <palmtenor@gmail.com>
Sun, 31 Jul 2016 17:17:07 +0000 (10:17 -0700)
committer4ast <alexei.starovoitov@gmail.com>
Sun, 31 Jul 2016 17:17:07 +0000 (10:17 -0700)
Recent USDT change removed `procstat.py`, which the `argdist` and `trace` tools are still referencing. This diff moves the only method (`which`) they are using into the `BPF` class.

Also, make `BPF.find_library` not to call `decode()` on `None`.

src/python/bcc/__init__.py
tools/argdist.py
tools/trace.py

index 7cb5fb8..e1469dc 100644 (file)
@@ -118,6 +118,35 @@ class BPF(object):
                     raise Exception("Could not find file %s" % filename)
         return filename
 
+    @staticmethod
+    def _find_exe(cls, bin_path):
+        """
+        _find_exe(bin_path)
+
+        Traverses the PATH environment variable, looking for the first
+        directory that contains an executable file named bin_path, and
+        returns the full path to that file, or None if no such file
+        can be found. This is meant to replace invocations of the
+        "which" shell utility, which doesn't have portable semantics
+        for skipping aliases.
+        """
+        # Source: http://stackoverflow.com/a/377028
+        def is_exe(fpath):
+            return os.path.isfile(fpath) and \
+                os.access(fpath, os.X_OK)
+
+        fpath, fname = os.path.split(bin_path)
+        if fpath:
+            if is_exe(bin_path):
+                return bin_path
+        else:
+            for path in os.environ["PATH"].split(os.pathsep):
+                path = path.strip('"')
+                exe_file = os.path.join(path, bin_path)
+                if is_exe(exe_file):
+                    return exe_file
+        return None
+
     def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0,
             cflags=[], usdt=None):
         """Create a a new BPF module with the given source code.
@@ -487,7 +516,8 @@ class BPF(object):
 
     @staticmethod
     def find_library(libname):
-        return lib.bcc_procutils_which_so(libname.encode("ascii")).decode()
+        res = lib.bcc_procutils_which_so(libname.encode("ascii"))
+        return res if res is None else res.decode()
 
     def attach_tracepoint(self, tp="", fn_name="", pid=-1, cpu=0, group_fd=-1):
         """attach_tracepoint(tp="", fn_name="", pid=-1, cpu=0, group_fd=-1)
index 36d0425..fa9276c 100755 (executable)
@@ -371,7 +371,7 @@ int PROBENAME(struct pt_regs *ctx SIGNATURE)
         def _attach_u(self):
                 libpath = BPF.find_library(self.library)
                 if libpath is None:
-                        libpath = ProcUtils.which(self.library)
+                        libpath = BPF._find_exe(self.library)
                 if libpath is None or len(libpath) == 0:
                         self._bail("unable to find library %s" % self.library)
 
index 8fff394..d4b604b 100755 (executable)
@@ -9,7 +9,7 @@
 # Licensed under the Apache License, Version 2.0 (the "License")
 # Copyright (C) 2016 Sasha Goldshtein.
 
-from bcc import BPF, Tracepoint, Perf, ProcUtils, USDT
+from bcc import BPF, Tracepoint, Perf, USDT
 from time import sleep, strftime
 import argparse
 import re
@@ -416,7 +416,7 @@ BPF_PERF_OUTPUT(%s);
                 libpath = BPF.find_library(self.library)
                 if libpath is None:
                         # This might be an executable (e.g. 'bash')
-                        libpath = ProcUtils.which(self.library)
+                        libpath = BPF._find_exe(self.library)
                 if libpath is None or len(libpath) == 0:
                         self._bail("unable to find library %s" % self.library)