bt2: rename CreationError to MemoryError, handle it in and out of Python bindings
authorSimon Marchi <simon.marchi@efficios.com>
Tue, 23 Jul 2019 06:08:59 +0000 (02:08 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Wed, 24 Jul 2019 04:18:54 +0000 (00:18 -0400)
Babeltrace API calls can explicitly return the MEMORY_ERROR status,
which is currently converted to a bt2.Error in Python.  If this
bt2.Error goes back to the native side of the bindings, is is converted
back to the ERROR status.  This is not ideal, as the status value should
stay MEMORY_ERROR when unwinding the stack.

Also, when creation functions fail (return NULL/None), we currently
raise a CreationError.  Those creation functions only return NULL/None
if there were memory issues, there is not other way they can
legitimately fail (otherwise they would return a status).  So it would
make sense for this to be reported as a MEMORY_ERROR.

To address these two issues, this patch:

- renames bt2.CreationError to bt2.MemoryError
- makes utils._handle_func_status raise a bt2.MemoryError when receiving
the MEMORY_ERROR status
- makes the native bindings return MEMORY_ERROR when catching a
bt2.MemoryError

Since there's no easy way to generate an actual MemoryError, I tested
this manually by hacking bt_graph_create to make it fail.

Change-Id: I4969e8ccd9618d8361fe45d0973df980bc9b7abd
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1751
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
14 files changed:
src/bindings/python/bt2/bt2/__init__.py.in
src/bindings/python/bt2/bt2/component.py
src/bindings/python/bt2/bt2/field_class.py
src/bindings/python/bt2/bt2/graph.py
src/bindings/python/bt2/bt2/integer_range_set.py
src/bindings/python/bt2/bt2/message_iterator.py
src/bindings/python/bt2/bt2/native_bt_component_class.i
src/bindings/python/bt2/bt2/port.py
src/bindings/python/bt2/bt2/query_executor.py
src/bindings/python/bt2/bt2/stream.py
src/bindings/python/bt2/bt2/trace.py
src/bindings/python/bt2/bt2/trace_class.py
src/bindings/python/bt2/bt2/utils.py
src/bindings/python/bt2/bt2/value.py

index ba17f1bed030ef01e8d445c44ed132fa0ca896bc..e98e4fb0501a347eff6b0c12973a07396fff00fa 100644 (file)
@@ -68,8 +68,8 @@ from bt2.value import _IntegerValue
 from bt2.clock_snapshot import _UnknownClockSnapshot
 
 
-class CreationError(Error):
-    '''Raised when object creation fails due to memory issues.'''
+class MemoryError(Error):
+    '''Raised when an operation fails due to memory issues.'''
 
 
 class InvalidObject(Exception):
index 07cccec90e035a1b8d800c23e0063445ef046823..cd1cf2dd49722ca1b1fd981a7d448760b49b4fc5 100644 (file)
@@ -499,7 +499,7 @@ class _UserComponentType(type):
             )
 
         if cc_ptr is None:
-            raise bt2.CreationError(
+            raise bt2.MemoryError(
                 "cannot create component class '{}'".format(class_name)
             )
 
@@ -677,7 +677,7 @@ class _UserComponent(metaclass=_UserComponentType):
         tc_ptr = native_bt.trace_class_create(ptr)
 
         if tc_ptr is None:
-            raise bt2.CreationError('could not create trace class')
+            raise bt2.MemoryError('could not create trace class')
 
         tc = bt2._TraceClass._create_from_ptr(tc_ptr)
         tc._assigns_automatic_stream_class_id = assigns_automatic_stream_class_id
@@ -698,7 +698,7 @@ class _UserComponent(metaclass=_UserComponentType):
         cc_ptr = native_bt.clock_class_create(ptr)
 
         if cc_ptr is None:
-            raise bt2.CreationError('could not create clock class')
+            raise bt2.MemoryError('could not create clock class')
 
         cc = bt2.clock_class._ClockClass._create_from_ptr(cc_ptr)
 
index 06980b393bc2ade4b6fa06ec35d33246d422e43e..7f25136889e3d494573f52ff5d664d857492ac9f 100644 (file)
@@ -46,7 +46,7 @@ class _FieldClass(object._SharedObject):
 
     def _check_create_status(self, ptr):
         if ptr is None:
-            raise bt2.CreationError(
+            raise bt2.MemoryError(
                 'cannot create {} field class object'.format(self._NAME.lower())
             )
 
index 870ddb381956406c6e79b878c8baa8db178f2e22..23467468595e49c564c03560979c375c2884b5aa 100644 (file)
@@ -73,7 +73,7 @@ class Graph(object._SharedObject):
         ptr = native_bt.graph_create()
 
         if ptr is None:
-            raise bt2.CreationError('cannot create graph object')
+            raise bt2.MemoryError('cannot create graph object')
 
         super().__init__(ptr)
 
@@ -196,6 +196,6 @@ class Graph(object._SharedObject):
         )
 
         if msg_iter_ptr is None:
-            raise bt2.CreationError('cannot create output port message iterator')
+            raise bt2.MemoryError('cannot create output port message iterator')
 
         return bt2.message_iterator._OutputPortMessageIterator(msg_iter_ptr)
index f7222fefbbe1e9e5bb0eb2077e896b78249f9b08..913422c1f673e8d156bc76bf2e0f749ce2d5935e 100644 (file)
@@ -72,7 +72,7 @@ class _IntegerRangeSet(object._SharedObject, collections.abc.MutableSet):
         ptr = self._create_range_set()
 
         if ptr is None:
-            raise bt2.CreationError('cannot create range set object')
+            raise bt2.MemoryError('cannot create range set object')
 
         super().__init__(ptr)
 
index 9d3a4d22f1bda9e6c3dbfeac6cea0bc3b3402f53..4457fc580acc368ca40a0aaa0b4797cd682d9362 100644 (file)
@@ -220,7 +220,7 @@ class _UserMessageIterator(_MessageIterator):
                 )
 
         if ptr is None:
-            raise bt2.CreationError('cannot create event message object')
+            raise bt2.MemoryError('cannot create event message object')
 
         return bt2.message._EventMessage(ptr)
 
@@ -231,7 +231,7 @@ class _UserMessageIterator(_MessageIterator):
         )
 
         if ptr is None:
-            raise bt2.CreationError('cannot create inactivity message object')
+            raise bt2.MemoryError('cannot create inactivity message object')
 
         return bt2.message._MessageIteratorInactivityMessage(ptr)
 
@@ -240,7 +240,7 @@ class _UserMessageIterator(_MessageIterator):
 
         ptr = native_bt.message_stream_beginning_create(self._bt_ptr, stream._ptr)
         if ptr is None:
-            raise bt2.CreationError('cannot create stream beginning message object')
+            raise bt2.MemoryError('cannot create stream beginning message object')
 
         msg = bt2.message._StreamBeginningMessage(ptr)
 
@@ -254,7 +254,7 @@ class _UserMessageIterator(_MessageIterator):
 
         ptr = native_bt.message_stream_end_create(self._bt_ptr, stream._ptr)
         if ptr is None:
-            raise bt2.CreationError('cannot create stream end message object')
+            raise bt2.MemoryError('cannot create stream end message object')
 
         msg = bt2.message._StreamEndMessage(ptr)
 
@@ -285,7 +285,7 @@ class _UserMessageIterator(_MessageIterator):
             ptr = native_bt.message_packet_beginning_create(self._bt_ptr, packet._ptr)
 
         if ptr is None:
-            raise bt2.CreationError('cannot create packet beginning message object')
+            raise bt2.MemoryError('cannot create packet beginning message object')
 
         return bt2.message._PacketBeginningMessage(ptr)
 
@@ -311,7 +311,7 @@ class _UserMessageIterator(_MessageIterator):
             ptr = native_bt.message_packet_end_create(self._bt_ptr, packet._ptr)
 
         if ptr is None:
-            raise bt2.CreationError('cannot create packet end message object')
+            raise bt2.MemoryError('cannot create packet end message object')
 
         return bt2.message._PacketEndMessage(ptr)
 
@@ -343,7 +343,7 @@ class _UserMessageIterator(_MessageIterator):
             ptr = native_bt.message_discarded_events_create(self._bt_ptr, stream._ptr)
 
         if ptr is None:
-            raise bt2.CreationError('cannot discarded events message object')
+            raise bt2.MemoryError('cannot discarded events message object')
 
         msg = bt2.message._DiscardedEventsMessage(ptr)
 
@@ -380,7 +380,7 @@ class _UserMessageIterator(_MessageIterator):
             ptr = native_bt.message_discarded_packets_create(self._bt_ptr, stream._ptr)
 
         if ptr is None:
-            raise bt2.CreationError('cannot discarded packets message object')
+            raise bt2.MemoryError('cannot discarded packets message object')
 
         msg = bt2.message._DiscardedPacketsMessage(ptr)
 
index b9e91a4af86e83c9864bb89b8fc1998865aeb909..dac194b3ae57c182453b2b95c013b151f1feb944 100644 (file)
@@ -94,6 +94,7 @@ PyObject *lookup_cc_ptr_to_py_cls(const bt_component_class *bt_cc)
 
 static PyObject *py_mod_bt2 = NULL;
 static PyObject *py_mod_bt2_exc_error_type = NULL;
+static PyObject *py_mod_bt2_exc_memory_error = NULL;
 static PyObject *py_mod_bt2_exc_try_again_type = NULL;
 static PyObject *py_mod_bt2_exc_stop_type = NULL;
 static PyObject *py_mod_bt2_exc_msg_iter_canceled_type = NULL;
@@ -117,6 +118,9 @@ void bt_bt2_cc_init_from_bt2(void)
        py_mod_bt2_exc_error_type =
                PyObject_GetAttrString(py_mod_bt2, "Error");
        BT_ASSERT(py_mod_bt2_exc_error_type);
+       py_mod_bt2_exc_memory_error =
+               PyObject_GetAttrString(py_mod_bt2, "MemoryError");
+       BT_ASSERT(py_mod_bt2_exc_memory_error);
        py_mod_bt2_exc_try_again_type =
                PyObject_GetAttrString(py_mod_bt2, "TryAgain");
        BT_ASSERT(py_mod_bt2_exc_try_again_type);
@@ -408,7 +412,13 @@ int py_exc_to_status(bt_self_component_class *self_component_class,
                log_exception_and_maybe_append_error(BT_LOG_WARNING, true,
                        self_component_class, self_component,
                        self_message_iterator, module_name);
-               status = __BT_FUNC_STATUS_ERROR;
+
+               if (PyErr_GivenExceptionMatches(exc,
+                               py_mod_bt2_exc_memory_error)) {
+                       status = __BT_FUNC_STATUS_MEMORY_ERROR;
+               } else {
+                       status = __BT_FUNC_STATUS_ERROR;
+               }
        }
 
 end:
index 1d649b35d72f4a6ec8a15a871cfec5400e8e5185..ecee18ce47b7eaa65dca8a218136572f9cd26c2a 100644 (file)
@@ -119,7 +119,7 @@ class _UserComponentInputPort(_UserComponentPort, _InputPort):
             self._ptr
         )
         if msg_iter_ptr is None:
-            raise bt2.CreationError('cannot create message iterator object')
+            raise bt2.MemoryError('cannot create message iterator object')
 
         return bt2.message_iterator._UserComponentInputPortMessageIterator(msg_iter_ptr)
 
index 17ddd97e86fd3d86563ad618266acf540637a1ce..a59bc79346546748773cd48f92c400e604511eef 100644 (file)
@@ -34,7 +34,7 @@ class QueryExecutor(object._SharedObject):
         ptr = native_bt.query_executor_create()
 
         if ptr is None:
-            raise bt2.CreationError('cannot create query executor object')
+            raise bt2.MemoryError('cannot create query executor object')
 
         super().__init__(ptr)
 
index 70011758cefaa01b0b2e4bd44e610de676cae606..2e75990deff5b31a6fcfdb1a3cf646542bee9048 100644 (file)
@@ -62,6 +62,6 @@ class _Stream(bt2.object._SharedObject):
         packet_ptr = native_bt.packet_create(self._ptr)
 
         if packet_ptr is None:
-            raise bt2.CreationError('cannot create packet object')
+            raise bt2.MemoryError('cannot create packet object')
 
         return bt2.packet._Packet._create_from_ptr(packet_ptr)
index 86bd90d05ae1d58844e9654a2f6009fe3eb0d3b1..5516a986daaa00893e9f626d654686a6b28b5f9b 100644 (file)
@@ -166,7 +166,7 @@ class _Trace(object._SharedObject, collections.abc.Mapping):
             )
 
         if stream_ptr is None:
-            raise bt2.CreationError('cannot create stream object')
+            raise bt2.MemoryError('cannot create stream object')
 
         stream = bt2.stream._Stream._create_from_ptr(stream_ptr)
 
index 8032ed117b88532f3728c252aef55384804de33a..798dbee07558fc81ef399c60e679330612b5ddbd 100644 (file)
@@ -69,7 +69,7 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
         trace_ptr = native_bt.trace_create(self._ptr)
 
         if trace_ptr is None:
-            raise bt2.CreationError('cannot create trace class object')
+            raise bt2.MemoryError('cannot create trace class object')
 
         trace = bt2.trace._Trace._create_from_ptr(trace_ptr)
 
@@ -204,7 +204,7 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
 
     def _check_create_status(self, ptr, type_name):
         if ptr is None:
-            raise bt2.CreationError('cannot create {} field class'.format(type_name))
+            raise bt2.MemoryError('cannot create {} field class'.format(type_name))
 
     def _create_integer_field_class(
         self, create_func, py_cls, type_name, field_value_range, preferred_display_base
index 8d5c4e2feecd0e2e6f1b10361916b1b27668ac44..023ff0a8062ef06b2b34be41ccc294d460471dff 100644 (file)
@@ -135,12 +135,12 @@ def _handle_func_status(status, msg=None):
         # no error
         return
 
-    if (
-        status == native_bt.__BT_FUNC_STATUS_ERROR
-        or status == native_bt.__BT_FUNC_STATUS_MEMORY_ERROR
-    ):
+    if status == native_bt.__BT_FUNC_STATUS_ERROR:
         assert msg is not None
         raise bt2.Error(msg)
+    elif status == native_bt.__BT_FUNC_STATUS_MEMORY_ERROR:
+        assert msg is not None
+        raise bt2.MemoryError(msg)
     elif status == native_bt.__BT_FUNC_STATUS_END:
         if msg is None:
             raise bt2.Stop
index 9ba010869a9875382dd73716dbb75a78c62b4b57..2c9476604be8b337228716a4956b02dc8e4564ad 100644 (file)
@@ -92,7 +92,7 @@ class _Value(object._SharedObject, metaclass=abc.ABCMeta):
 
     def _check_create_status(self, ptr):
         if ptr is None:
-            raise bt2.CreationError(
+            raise bt2.MemoryError(
                 'cannot create {} value object'.format(self._NAME.lower())
             )
 
This page took 0.032394 seconds and 4 git commands to generate.