Skip to content

Commit

Permalink
u* tools: Gracefully handle missing probes
Browse files Browse the repository at this point in the history
When the target process is missing the required USDT probes, it can
be a simple mistake (e.g. attaching a script as Java to a Python
process), or a runtime that is not instrumented with the required
probes. Attempt to gracefully handle the error and print a helpful
message instructing the user why the error might have occurred.

```
$ uthreads -l java $(pidof python)
Error attaching USDT probes: the specified pid might not contain
the given language's runtime, or the runtime was not built with the
required USDT probes. Look for a configure flag similar to
--with-dtrace or --enable-dtrace. To check which probes are present
in the process, use the tplist tool.
```
  • Loading branch information
goldshtn committed Feb 13, 2017
1 parent 6e1fac4 commit dc3a57c
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/python/bcc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,4 +1065,4 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self.cleanup()


from .usdt import USDT
from .usdt import USDT, USDTException
36 changes: 27 additions & 9 deletions src/python/bcc/usdt.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@
# limitations under the License.

import ctypes as ct
import sys
from .libbcc import lib, _USDT_CB, _USDT_PROBE_CB, \
bcc_usdt_location, bcc_usdt_argument, \
BCC_USDT_ARGUMENT_FLAGS

class USDTException(Exception):
pass

class USDTProbeArgument(object):
def __init__(self, argument):
self.signed = argument.size < 0
Expand Down Expand Up @@ -77,8 +81,9 @@ def get_argument(self, index):
res = lib.bcc_usdt_get_argument(self.probe.context, self.probe.name,
self.index, index, ct.pointer(arg))
if res != 0:
raise Exception("error retrieving probe argument %d location %d" %
(index, self.index))
raise USDTException(
"error retrieving probe argument %d location %d" %
(index, self.index))
return USDTProbeArgument(arg)

class USDTProbe(object):
Expand All @@ -103,7 +108,7 @@ def get_location(self, index):
res = lib.bcc_usdt_get_location(self.context, self.name,
index, ct.pointer(loc))
if res != 0:
raise Exception("error retrieving probe location %d" % index)
raise USDTException("error retrieving probe location %d" % index)
return USDTProbeLocation(self, index, loc)

class USDT(object):
Expand All @@ -112,20 +117,33 @@ def __init__(self, pid=None, path=None):
self.pid = pid
self.context = lib.bcc_usdt_new_frompid(pid)
if self.context == None:
raise Exception("USDT failed to instrument PID %d" % pid)
raise USDTException("USDT failed to instrument PID %d" % pid)
elif path:
self.path = path
self.context = lib.bcc_usdt_new_frompath(path)
if self.context == None:
raise Exception("USDT failed to instrument path %s" % path)
raise USDTException("USDT failed to instrument path %s" % path)
else:
raise Exception("either a pid or a binary path must be specified")
raise USDTException(
"either a pid or a binary path must be specified")

def enable_probe(self, probe, fn_name):
if lib.bcc_usdt_enable_probe(self.context, probe, fn_name) != 0:
raise Exception(("failed to enable probe '%s'; a possible cause " +
"can be that the probe requires a pid to enable") %
probe)
raise USDTException(
("failed to enable probe '%s'; a possible cause " +
"can be that the probe requires a pid to enable") %
probe
)

def enable_probe_or_bail(self, probe, fn_name):
if lib.bcc_usdt_enable_probe(self.context, probe, fn_name) != 0:
print(
"""Error attaching USDT probes: the specified pid might not contain the
given language's runtime, or the runtime was not built with the required
USDT probes. Look for a configure flag similar to --with-dtrace or
--enable-dtrace. To check which probes are present in the process, use the
tplist tool.""")
sys.exit(1)

def get_text(self):
return lib.bcc_usdt_genargs(self.context).decode()
Expand Down
4 changes: 2 additions & 2 deletions tools/ucalls.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@

if args.language:
usdt = USDT(pid=args.pid)
usdt.enable_probe(entry_probe, "trace_entry")
usdt.enable_probe_or_bail(entry_probe, "trace_entry")
if args.latency:
usdt.enable_probe(return_probe, "trace_return")
usdt.enable_probe_or_bail(return_probe, "trace_return")
else:
usdt = None

Expand Down
2 changes: 1 addition & 1 deletion tools/uflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def enable_probe(probe_name, func_name, read_class, read_method, is_return):
.replace("FILTER_METHOD", filter_method) \
.replace("DEPTH", depth) \
.replace("UPDATE", update)
usdt.enable_probe(probe_name, func_name)
usdt.enable_probe_or_bail(probe_name, func_name)

usdt = USDT(pid=args.pid)

Expand Down
4 changes: 2 additions & 2 deletions tools/ugc.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ def generate(self):
return text

def attach(self):
usdt.enable_probe(self.begin, "trace_%s" % self.begin)
usdt.enable_probe(self.end, "trace_%s" % self.end)
usdt.enable_probe_or_bail(self.begin, "trace_%s" % self.begin)
usdt.enable_probe_or_bail(self.end, "trace_%s" % self.end)

def format(self, data):
return self.formatter(data)
Expand Down
6 changes: 3 additions & 3 deletions tools/uobjnew.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
return 0;
}
"""
usdt.enable_probe("object__alloc", "alloc_entry")
usdt.enable_probe_or_bail("object__alloc", "alloc_entry")
#
# Ruby
#
Expand Down Expand Up @@ -107,10 +107,10 @@
return 0;
}
"""
usdt.enable_probe("object__create", "object_alloc_entry")
usdt.enable_probe_or_bail("object__create", "object_alloc_entry")
for thing in ["string", "hash", "array"]:
program += create_template.replace("THETHING", thing)
usdt.enable_probe("%s__create" % thing, "%s_alloc_entry" % thing)
usdt.enable_probe_or_bail("%s__create" % thing, "%s_alloc_entry" % thing)
#
# C
#
Expand Down
6 changes: 3 additions & 3 deletions tools/uthreads.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
return 0;
}
"""
usdt.enable_probe("pthread_start", "trace_pthread")
usdt.enable_probe_or_bail("pthread_start", "trace_pthread")

if args.language == "java":
template = """
Expand All @@ -78,8 +78,8 @@
"""
program += template % ("trace_start", "start")
program += template % ("trace_stop", "stop")
usdt.enable_probe("thread__start", "trace_start")
usdt.enable_probe("thread__stop", "trace_stop")
usdt.enable_probe_or_bail("thread__start", "trace_start")
usdt.enable_probe_or_bail("thread__stop", "trace_stop")

if args.verbose:
print(usdt.get_text())
Expand Down

0 comments on commit dc3a57c

Please sign in to comment.