Skip to content

Commit

Permalink
Merge pull request iovisor#1705 from palmtenor/profilestack
Browse files Browse the repository at this point in the history
Refactor profile.py stack id error handling
  • Loading branch information
yonghong-song committed Apr 26, 2018
2 parents 84664dc + e4db768 commit 19b61eb
Showing 1 changed file with 44 additions and 27 deletions.
71 changes: 44 additions & 27 deletions tools/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def positive_nonzero_int(val):
raise argparse.ArgumentTypeError("must be nonzero")
return ival

def stack_id_err(stack_id):
# -EFAULT in get_stackid normally means the stack-trace is not availible,
# Such as getting kernel stack trace in userspace code
return (stack_id < 0) and (stack_id != -errno.EFAULT)

# arguments
examples = """examples:
./profile # profile stack traces at 49 Hertz until Ctrl-C
Expand Down Expand Up @@ -201,11 +206,8 @@ def positive_nonzero_int(val):
bpf_text = bpf_text.replace('STACK_STORAGE_SIZE', str(args.stack_storage_size))

# handle stack args
kernel_stack_get = \
"stack_traces.get_stackid(&ctx->regs, 0 | BPF_F_REUSE_STACKID)"
user_stack_get = \
"stack_traces.get_stackid(&ctx->regs, 0 | BPF_F_REUSE_STACKID | " \
"BPF_F_USER_STACK)"
kernel_stack_get = "stack_traces.get_stackid(&ctx->regs, 0)"
user_stack_get = "stack_traces.get_stackid(&ctx->regs, BPF_F_USER_STACK)"
stack_context = ""
if args.user_stacks_only:
stack_context = "user"
Expand Down Expand Up @@ -279,17 +281,16 @@ def aksym(addr):
has_enomem = False
counts = b.get_table("counts")
stack_traces = b.get_table("stack_traces")
need_delimiter = args.delimited and not (args.kernel_stacks_only or
args.user_stacks_only)
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
# handle get_stackid erorrs
if (not args.user_stacks_only and k.kernel_stack_id < 0 and
k.kernel_stack_id != -errno.EFAULT) or \
(not args.kernel_stacks_only and k.user_stack_id < 0 and
k.user_stack_id != -errno.EFAULT):
# handle get_stackid errors
if not args.user_stacks_only and stack_id_err(k.kernel_stack_id):
missing_stacks += 1
# check for an ENOMEM error
if k.kernel_stack_id == -errno.ENOMEM or \
k.user_stack_id == -errno.ENOMEM:
has_enomem = True
has_enomem = has_enomem or k.kernel_stack_id == -errno.ENOMEM
if not args.kernel_stacks_only and stack_id_err(k.user_stack_id):
missing_stacks += 1
has_enomem = has_enomem or k.user_stack_id == -errno.ENOMEM

user_stack = [] if k.user_stack_id < 0 else \
stack_traces.walk(k.user_stack_id)
Expand All @@ -305,25 +306,41 @@ def aksym(addr):
if k.kernel_ip:
kernel_stack.insert(0, k.kernel_ip)

do_delimiter = need_delimiter and kernel_stack

if args.folded:
# print folded stack output
user_stack = list(user_stack)
kernel_stack = list(kernel_stack)
line = [k.name.decode()] + \
[b.sym(addr, k.pid) for addr in reversed(user_stack)] + \
(do_delimiter and ["-"] or []) + \
[aksym(addr) for addr in reversed(kernel_stack)]
line = [k.name.decode()]
# if we failed to get the stack is, such as due to no space (-ENOMEM) or
# hash collision (-EEXIST), we still print a placeholder for consistency
if not args.kernel_stacks_only:
if stack_id_err(k.user_stack_id):
line.append("[Missed User Stack]")
else:
line.extend([b.sym(addr, k.pid) for addr in reversed(user_stack)])
if not args.user_stacks_only:
line.extend(["-"] if (need_delimiter and k.kernel_stack_id >= 0 and k.user_stack_id >= 0) else [])
if stack_id_err(k.kernel_stack_id):
line.append("[Missed Kernel Stack]")
else:
line.extend([b.ksym(addr) for addr in reversed(kernel_stack)])
print("%s %d" % (";".join(line), v.value))
else:
# print default multi-line stack output.
for addr in kernel_stack:
print(" %s" % aksym(addr))
if do_delimiter:
print(" --")
for addr in user_stack:
print(" %s" % b.sym(addr, k.pid))
# print default multi-line stack output
if not args.user_stacks_only:
if stack_id_err(k.kernel_stack_id):
print(" [Missed Kernel Stack]")
else:
for addr in kernel_stack:
print(" %s" % aksym(addr))
if not args.kernel_stacks_only:
if need_delimiter and k.user_stack_id >= 0 and k.kernel_stack_id >= 0:
print(" --")
if stack_id_err(k.user_stack_id):
print(" [Missed User Stack]")
else:
for addr in user_stack:
print(" %s" % b.sym(addr, k.pid))
print(" %-16s %s (%d)" % ("-", k.name.decode(), k.pid))
print(" %d\n" % v.value)

Expand Down

0 comments on commit 19b61eb

Please sign in to comment.