Project

General

Profile

Actions

Bug #1052

closed

Python 3 exit code 139 with repeated requests of EventDeclaration

Added by Daniel U. Thibault almost 8 years ago. Updated over 3 years ago.

Status:
Invalid
Priority:
Normal
Assignee:
-
Category:
-
Target version:
-
Start date:
07/19/2016
Due date:
% Done:

0%

Estimated time:

Description

Using Python 3.2.3 on Ubuntu 14.04.4 through PyCharm Community Edition 2016.1.3, build #PC-145.971, JRE: 1.8.0_76-release-b32 amd64, JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

#!/usr/bin/python3
import babeltrace

def some_events(trace_collection, number):
    n_names = 0
    for event in trace_collection.events:
        n_names += 1
        print("{0:s}:".format(event.name))
        n_decl = 0
        for decl in event.handle.events:
            n_decl += 1
        print("   {0:d} declarations".format(n_decl))
        if (number is not None) and (n_names >= number):
            break

trace_path = "/home/daniel/lttng-traces/ffx-session-20160706-141412.0/kernel" 

trace_collection = babeltrace.TraceCollection()

trace_handle = trace_collection.add_trace(trace_path, 'ctf')

print("first three events:")
some_events(trace_collection, 3)
print("some_events done.")

print("All done.")

Results in:

/usr/bin/python3.2mu /home/daniel/pycharm-community-2016.1.3/helpers/pydev/pydevd.py --multiproc --qt-support --client 127.0.0.1 --port 58138 --file /home/daniel/PycharmProjects/untitled/ltrace_examples.py
pydev debugger: process 8756 is connecting

Connected to pydev debugger (build 145.971)
first three events:
syscall_exit_epoll_wait:
   12826 declarations
syscall_entry_ioctl:
   12826 declarations

Process finished with exit code 139

The exit occurs on the for event in trace_collection.events: line when the third event (which is quite valid) should be generated. Exit code 139 is SIGSEGV, "attempt to access a virtual address which is not in your address space", and is probably an out-of-memory error. Maybe a major memory leak? I tried importing gc and calling gc.collect() right after each inner loop: it collects no objects.

(The set of @EventDeclaration@s is unchanging for a given trace; but there could be cases where one wants to interrogate the @EventDeclaration@s of a collection of several traces)

Actions #1

Updated by Daniel U. Thibault almost 8 years ago

If I use the trace_handle from the TraceCollection.add_trace or if I recover it from a piece of code like:

    for event in trace_collection.events:
        trace1 = event.handle
        break

Then I can loop over the set of EventDeclaration as many times as I like without triggering exit code 139:
    while True:
        n_decl = 0
        for decl in trace_handle.events:
            n_decl += 1
        print("   {0:d} declarations".format(n_decl))

So it looks like it's not a memory leak but rather more about a handle-like value that goes out of context. You can get an exit code 139 if you grab the first event from the for event in trace_collection.events: loop, break out of the loop, then try to use that value. This is a stronger constraint than the one appearing in the documentation, http://diamon.org/babeltrace/docs/python/reader/ :
Due to limitations of the native Babeltrace API, only one event may be "alive" at a given time, i.e. a user should never store a copy of the events returned by this function for ulterior use. Users shall make sure to copy the information they need from an event before accessing the next one.

That warning boils down to "you can't use an event reference once the iterator has moved on to the next one". It needs to be broadened to "you can't use an event reference once the iterator has moved on to the next one or gone out of scope".

Actions #2

Updated by Daniel U. Thibault almost 8 years ago

Here's an even simpler case:

def some_events(trace_collection, number):
    n_events = 0
    path = None
    for event in trace_collection.events:
        th = event.handle
        n_events += 1
        print("Trace handles obtained: {0:d}".format(n_events))

This loop will crash (at the for event in trace_collection.events: line) with exit code 139 when it tries to read the fourth event.

Actions #3

Updated by Daniel U. Thibault over 7 years ago

This is a very annoying bug that is getting in the way of our trace analyses (and should be treated as high priority). For instance, reading a bunch of sequential (non-overlapping in time) traces and then trying to treat them one at a time with:

traces = babeltrace.TraceCollection()
trace_handles = traces.add_traces_recursive(traces_path, 'ctf')
handle = None
for event in traces.events:
    if (handle is None) or (handle.id != event.handle.id):
        # New trace (they don't overlap)
        handle = event.handle
        print("Trace {0}".format(handle.path))
    ...

will fail miserably with an exit code 139 on the third event.

Actions #4

Updated by Jérémie Galarneau over 7 years ago

I agree that the warning should be clarified.
Do you have a trace that reproduces the problem?

Actions #5

Updated by Daniel U. Thibault over 7 years ago

Here's a self-contained script and a small (kernel system call) trace that chokes on the third pass through the EventDeclarations. You'll have to adapt the trace_path

#!/usr/bin/python3
import sys, babeltrace

def some_events(trace_collection, number):
    n_names = 0
    for event in trace_collection.events:
        n_names += 1
        print("{0:s}:".format(event.name))
        n_decl = 0
        for decl in event.handle.events:
            n_decl += 1
        print("   {0:d} declarations".format(n_decl))
        if (number is not None) and (n_names >= number):
            break

def main(argv):
    """ 
    The main function.
    :param argv: the list of command-line arguments, excluding the executable name
    :return: Nothing
    """ 
    trace_path = "/home/daniel/lttng-traces/smallsession-20160803-143625/kernel" 

    trace_collection = babeltrace.TraceCollection()

    trace_handle = trace_collection.add_trace(trace_path, 'ctf')

    print("first three events:")
    some_events(trace_collection, 3)
    print("some_events done.")

    print("All done.")

if __name__ == "__main__":
    main(sys.argv[1:])
Actions #6

Updated by Daniel U. Thibault over 7 years ago

Umm...Trouble uploading. It's a 1.1 MB zip...The button reads "ExecutableDownloadsNew" (truncated) after I've uploaded.

Actions #7

Updated by Jonathan Rajotte Julien about 4 years ago

  • Status changed from New to Invalid

State of babeltrace moved a lot since.

Closing this ticket as invalid. Reopen it if it stills apply to Babeltrace 2.

Actions

Also available in: Atom PDF