bt_message_array_const msgs, uint64_t capacity,
uint64_t *count)
{
- bt_component_class_message_iterator_next_method_status status =
- BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK;
+ bt_component_class_message_iterator_next_method_status status;
struct ctf_fs_msg_iter_data *msg_iter_data =
bt_self_message_iterator_get_data(iterator);
uint64_t i = 0;
- while (i < capacity &&
- status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK) {
+ if (G_UNLIKELY(msg_iter_data->next_saved_error)) {
+ /*
+ * Last time we were called, we hit an error but had some
+ * messages to deliver, so we stashed the error here. Return
+ * it now.
+ */
+ BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(msg_iter_data->next_saved_error);
+ status = msg_iter_data->next_saved_status;
+ goto end;
+ }
+
+ do {
status = ctf_fs_iterator_next_one(msg_iter_data, &msgs[i]);
if (status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK) {
i++;
}
- }
+ } while (i < capacity &&
+ status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK);
if (i > 0) {
/*
* called, possibly without any accumulated
* message, in which case we'll return it.
*/
+ if (status < 0) {
+ /*
+ * Save this error for the next _next call. Assume that
+ * this component always appends error causes when
+ * returning an error status code, which will cause the
+ * current thread error to be non-NULL.
+ */
+ msg_iter_data->next_saved_error = bt_current_thread_take_error();
+ BT_ASSERT(msg_iter_data->next_saved_error);
+ msg_iter_data->next_saved_status = status;
+ }
+
*count = i;
status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK;
}
+end:
return status;
}
/* Owned by this */
struct ctf_msg_iter *msg_iter;
+
+ /*
+ * Saved error. If we hit an error in the _next method, but have some
+ * messages ready to return, we save the error here and return it on
+ * the next _next call.
+ */
+ bt_component_class_message_iterator_next_method_status next_saved_status;
+ const struct bt_error *next_saved_error;
};
BT_HIDDEN
* MUXER_MSG_ITER_CLOCK_CLASS_EXPECTATION_NOT_ABS_SPEC_UUID.
*/
bt_uuid_t expected_clock_class_uuid;
+
+ /*
+ * Saved error. If we hit an error in the _next method, but have some
+ * messages ready to return, we save the error here and return it on
+ * the next _next call.
+ */
+ bt_component_class_message_iterator_next_method_status next_saved_status;
+ const struct bt_error *next_saved_error;
};
static
bt_message_array_const msgs, uint64_t capacity,
uint64_t *count)
{
- bt_component_class_message_iterator_next_method_status status =
- BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK;
+ bt_component_class_message_iterator_next_method_status status;
uint64_t i = 0;
- while (i < capacity && status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK) {
+ if (G_UNLIKELY(muxer_msg_iter->next_saved_error)) {
+ /*
+ * Last time we were called, we hit an error but had some
+ * messages to deliver, so we stashed the error here. Return
+ * it now.
+ */
+ BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(muxer_msg_iter->next_saved_error);
+ status = muxer_msg_iter->next_saved_status;
+ goto end;
+ }
+
+ do {
status = muxer_msg_iter_do_next_one(muxer_comp,
muxer_msg_iter, &msgs[i]);
if (status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK) {
i++;
}
- }
+ } while (i < capacity && status == BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK);
if (i > 0) {
/*
* called, possibly without any accumulated
* message, in which case we'll return it.
*/
+ if (status < 0) {
+ /*
+ * Save this error for the next _next call. Assume that
+ * this component always appends error causes when
+ * returning an error status code, which will cause the
+ * current thread error to be non-NULL.
+ */
+ muxer_msg_iter->next_saved_error = bt_current_thread_take_error();
+ BT_ASSERT(muxer_msg_iter->next_saved_error);
+ muxer_msg_iter->next_saved_status = status;
+ }
+
*count = i;
status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_OK;
}
+end:
return status;
}
--- /dev/null
+This trace was written by hand. It contains two valid events, followed by an
+invalid one (the event id is invalid).
--- /dev/null
+\ 1\ 1ÿ
\ No newline at end of file
--- /dev/null
+/* CTF 1.8 */
+
+typealias integer { size = 8; align = 8; signed = false; } := uint8_t;
+
+trace {
+ major = 1;
+ minor = 8;
+ byte_order = be;
+};
+
+stream {
+ event.header := struct {
+ uint8_t id;
+ };
+};
+
+
+event {
+ name = gadoua;
+ id = 1;
+};
--- /dev/null
+Trace class:
+ Stream class (ID 0):
+ Supports packets: Yes
+ Packets have beginning default clock snapshot: No
+ Packets have end default clock snapshot: No
+ Supports discarded events: No
+ Supports discarded packets: No
+ Event class `gadoua` (ID 1):
+
+{Trace 0, Stream class ID 0, Stream ID 0}
+Stream beginning:
+ Trace:
+ Stream (ID 0, Class ID 0)
+
+{Trace 0, Stream class ID 0, Stream ID 0}
+Packet beginning
+
+{Trace 0, Stream class ID 0, Stream ID 0}
+Event `gadoua` (Class ID 1):
+
+{Trace 0, Stream class ID 0, Stream ID 0}
+Event `gadoua` (Class ID 1):
stdout_file=$(mktemp -t test_ctf_fail_stdout.XXXXXX)
stderr_file=$(mktemp -t test_ctf_fail_stderr.XXXXXX)
+data_dir="${BT_TESTS_SRCDIR}/data/plugins/src.ctf.fs/fail"
test_fail() {
local name="$1"
- local expected_error_msg="$2"
+ local expected_stdout_file="$2"
+ local expected_error_msg="$3"
bt_cli "${stdout_file}" "${stderr_file}" \
- "${fail_trace_dir}/${name}"
+ -c sink.text.details -p "with-trace-name=no,with-stream-name=no" "${fail_trace_dir}/${name}"
isnt $? 0 "Trace ${name}: babeltrace exits with an error"
+ bt_diff "${expected_stdout_file}" "${stdout_file}"
+ ok $? "Trace ${name}: babeltrace produces the expected stdout"
+
+ # The expected error message will likely be found in the error stream
+ # even if Babeltrace aborts (e.g. hits an assert). Check that the
+ # Babeltrace CLI finishes gracefully by checking that the error stream
+ # contains an error stack printed by the CLI.
+ grep --silent "^CAUSED BY " "${stderr_file}"
+ ok $? "Trace ${name}: babeltrace produces an error stack"
+
grep --silent "${expected_error_msg}" "${stderr_file}"
ok $? "Trace ${name}: babeltrace produces the expected error message"
}
-plan_tests 2
+plan_tests 8
+
+test_fail \
+ "invalid-packet-size/trace" \
+ "/dev/null" \
+ "Failed to index CTF stream file '.*channel0_3'"
-test_fail "invalid-packet-size/trace" "Failed to index CTF stream file '.*channel0_3'"
+test_fail \
+ "valid-events-then-invalid-events" \
+ "${data_dir}/valid-events-then-invalid-events.expect" \
+ "No event class with ID of event class ID to use in stream class: .*stream-class-id=0, event-class-id=255"
rm -f "${stdout_file}" "${stderr_file}"