Python bindings: work around Python 3.5 behaviour change
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 29 Feb 2016 20:08:15 +0000 (15:08 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 29 Feb 2016 20:08:15 +0000 (15:08 -0500)
Python 3.5 changes the StopIteration exception clearing behaviour when
a generator finishes its iteration. This causes the interpreter to
errounously consider SWIG clean-up functions as having "set an error".

This hack explicitly allocates and cleans up struct bt_iter_pos
instead of relying on SWIG auto-generated code which manages
the lifetime of temporary objects.

An investigation of the cause of this change is under way, but at
least this makes the bindings usable on Python 3.5 which is
being rolled-out in some distros.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
bindings/python/babeltrace.i.in
bindings/python/python-complements.c
bindings/python/python-complements.h

index 5142952ec5fdeac715a28e01510354b29ed68f07..f07f2fb7af025f321e3664c39d0f424121f2a39c 100644 (file)
@@ -99,6 +99,7 @@ const char *_bt_python_get_array_string(struct bt_definition *field);
 const char *_bt_python_get_sequence_string(struct bt_definition *field);
 int _bt_python_field_integer_get_signedness(const struct bt_ctf_field *field);
 enum ctf_type_id _bt_python_get_field_type(const struct bt_ctf_field *field);
 const char *_bt_python_get_sequence_string(struct bt_definition *field);
 int _bt_python_field_integer_get_signedness(const struct bt_ctf_field *field);
 enum ctf_type_id _bt_python_get_field_type(const struct bt_ctf_field *field);
+struct bt_iter_pos *_bt_python_create_iter_pos(void);
 
 /* =================================================================
                CONTEXT.H, CONTEXT-INTERNAL.H
 
 /* =================================================================
                CONTEXT.H, CONTEXT-INTERNAL.H
@@ -223,21 +224,24 @@ class TraceCollection:
                event after the the generator has gone out of scope may result in a
                crash or data corruption.
                """
                event after the the generator has gone out of scope may result in a
                crash or data corruption.
                """
-               begin_pos_ptr = _bt_iter_pos()
-               end_pos_ptr = _bt_iter_pos()
+               begin_pos_ptr = _bt_python_create_iter_pos()
+               end_pos_ptr = _bt_python_create_iter_pos()
                begin_pos_ptr.type = SEEK_BEGIN
                end_pos_ptr.type = SEEK_LAST
 
                for event in self._events(begin_pos_ptr, end_pos_ptr):
                        yield event
 
                begin_pos_ptr.type = SEEK_BEGIN
                end_pos_ptr.type = SEEK_LAST
 
                for event in self._events(begin_pos_ptr, end_pos_ptr):
                        yield event
 
+               _bt_iter_free_pos(begin_pos_ptr)
+               _bt_iter_free_pos(end_pos_ptr)
+
        def events_timestamps(self, timestamp_begin, timestamp_end):
                """
                Generator function to iterate over the events of open in the current
                TraceCollection from timestamp_begin to timestamp_end.
                """
        def events_timestamps(self, timestamp_begin, timestamp_end):
                """
                Generator function to iterate over the events of open in the current
                TraceCollection from timestamp_begin to timestamp_end.
                """
-               begin_pos_ptr = _bt_iter_pos()
-               end_pos_ptr = _bt_iter_pos()
+               begin_pos_ptr = _bt_python_create_iter_pos()
+               end_pos_ptr = _bt_python_create_iter_pos()
                begin_pos_ptr.type = end_pos_ptr.type = SEEK_TIME
                begin_pos_ptr.u.seek_time = timestamp_begin
                end_pos_ptr.u.seek_time = timestamp_end
                begin_pos_ptr.type = end_pos_ptr.type = SEEK_TIME
                begin_pos_ptr.u.seek_time = timestamp_begin
                end_pos_ptr.u.seek_time = timestamp_end
@@ -245,6 +249,9 @@ class TraceCollection:
                for event in self._events(begin_pos_ptr, end_pos_ptr):
                        yield event
 
                for event in self._events(begin_pos_ptr, end_pos_ptr):
                        yield event
 
+               _bt_iter_free_pos(begin_pos_ptr)
+               _bt_iter_free_pos(end_pos_ptr)
+
        @property
        def timestamp_begin(self):
                pos_ptr = _bt_iter_pos()
        @property
        def timestamp_begin(self):
                pos_ptr = _bt_iter_pos()
index 6f947bd04e331cb3675a3820b8166e6e2af18e5f..52465aa229a83495ea2c46cba7d4be5559291042 100644 (file)
@@ -21,6 +21,8 @@
 #include "python-complements.h"
 #include <babeltrace/ctf-writer/event-types-internal.h>
 #include <babeltrace/ctf-writer/event-fields-internal.h>
 #include "python-complements.h"
 #include <babeltrace/ctf-writer/event-types-internal.h>
 #include <babeltrace/ctf-writer/event-fields-internal.h>
+#include <babeltrace/iterator.h>
+#include <glib.h>
 
 /* FILE functions
    ----------------------------------------------------
 
 /* FILE functions
    ----------------------------------------------------
@@ -236,3 +238,14 @@ enum ctf_type_id _bt_python_get_field_type(const struct bt_ctf_field *field)
 end:
        return type_id;
 }
 end:
        return type_id;
 }
+
+/*
+ * Python 3.5 changes the StopIteration exception clearing behaviour which
+ * erroneously marks swig clean-up function as having failed. This explicit
+ * allocation function is intended as a work-around so SWIG doesn't manage
+ * the lifetime of a "temporary" object by itself.
+ */
+struct bt_iter_pos *_bt_python_create_iter_pos(void)
+{
+       return g_new0(struct bt_iter_pos, 1);
+}
index 0e38e6b2ac4ce2574dbb538bbe7f03b0e693da65..bd2259805cd9b4b15172a52e0b557f435c92266d 100644 (file)
@@ -71,3 +71,6 @@ const char *_bt_python_get_sequence_string(struct bt_definition *field);
 /* ctf writer */
 int _bt_python_field_integer_get_signedness(const struct bt_ctf_field *field);
 enum ctf_type_id _bt_python_get_field_type(const struct bt_ctf_field *field);
 /* ctf writer */
 int _bt_python_field_integer_get_signedness(const struct bt_ctf_field *field);
 enum ctf_type_id _bt_python_get_field_type(const struct bt_ctf_field *field);
+
+/* iterator */
+struct bt_iter_pos *_bt_python_create_iter_pos(void);
This page took 0.028907 seconds and 4 git commands to generate.