Skip to content

Commit

Permalink
Add field support to trace_print and friends
Browse files Browse the repository at this point in the history
Add trace_readline_fields helper to parse the output of trace_pipe
Add field parsing support to trace_print. Addresses iovisor#149.
Fix typo in trace_open s/trace/tracefile/
Make nonblocking=False the default in trace_readline
Use IOError vs BlockingIOError for greater compatibility (untested)

Fixes: iovisor#149
Signed-off-by: Brenden Blanco <[email protected]>
  • Loading branch information
Brenden Blanco committed Aug 24, 2015
1 parent ee28632 commit 022f3d7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 17 deletions.
5 changes: 2 additions & 3 deletions examples/hello_world.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
# sudo ./hello_world.py"

from bpf import BPF
from subprocess import call

prog = """
int hello(void *ctx) {
bpf_trace_printk("Hello, World!\\n");
return 0;
};
}
"""
b = BPF(text=prog)
b.attach_kprobe(event="sys_clone", fn_name="hello")
b.trace_print()
b.trace_print(fmt="{1} {5}")
58 changes: 44 additions & 14 deletions src/python/bpf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ def attach_kprobe(self, event="", fn_name="", pid=0, cpu=-1, group_fd=-1):
if res < 0:
raise Exception("Failed to attach BPF to kprobe")
open_kprobes[ev_name] = res
return res
return self

@staticmethod
def detach_kprobe(event):
Expand All @@ -412,7 +412,7 @@ def attach_kretprobe(self, event="", fn_name="", pid=-1, cpu=0, group_fd=-1):
if res < 0:
raise Exception("Failed to attach BPF to kprobe")
open_kprobes[ev_name] = res
return res
return self

@staticmethod
def detach_kretprobe(event):
Expand All @@ -437,14 +437,33 @@ def trace_open(nonblocking=False):
if not tracefile:
tracefile = open("%s/trace_pipe" % TRACEFS)
if nonblocking:
fd = trace.fileno()
fd = tracefile.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
return tracefile

@staticmethod
def trace_readline(nonblocking=True):
"""trace_readline(nonblocking=True)
def trace_readline_fields(nonblocking=False):
"""trace_readline_fields(nonblocking=False)
Read from the kernel debug trace pipe and return a tuple of the
fields (task, pid, cpu, flags, timestamp, msg) or None if no
line was read (nonblocking=True)
"""
line = BPF.trace_readline(nonblocking)
if line:
task = line[:16].lstrip()
line = line[17:]
ts_end = line.find(":")
pid, cpu, flags, ts = line[:ts_end].split()
cpu = cpu[1:-1]
msg = line[ts_end + 4:]
return (task, int(pid), int(cpu), flags, float(ts), msg)
return

@staticmethod
def trace_readline(nonblocking=False):
"""trace_readline(nonblocking=False)
Read from the kernel debug trace pipe and return one line
If nonblocking is False, this will block until ctrl-C is pressed.
Expand All @@ -454,17 +473,28 @@ def trace_readline(nonblocking=True):

line = None
try:
line = trace.readline(128).rstrip()
except BlockingIOError:
line = trace.readline(1024).rstrip()
except IOError:
pass
except KeyboardInterrupt:
exit()
return line

@staticmethod
def trace_print():
try:
while True:
def trace_print(fmt=None):
"""trace_print(fmt=None)
Read from the kernel debug trace pipe and print on stdout.
If fmt is specified, apply as a format string to the output. See
trace_readline_fields for the members of the tuple
example: trace_print(fmt="pid {1}, msg = {5}")
"""

while True:
if fmt:
fields = BPF.trace_readline_fields(nonblocking=False)
line = fmt.format(*fields)
else:
line = BPF.trace_readline(nonblocking=False)
print(line)
sys.stdout.flush()
except KeyboardInterrupt:
exit()
print(line)
sys.stdout.flush()

0 comments on commit 022f3d7

Please sign in to comment.