Skip to content

Commit

Permalink
lib: add pre condition asserts to check current thread has no error
Browse files Browse the repository at this point in the history
The user must not call an API function while the current thread has an
error set, especially a function that can itself fail and set an error.
Otherwise, causes from two unrelated errors will end up in the same
stack, which will produce some misleading information.

Add a precondition assertion to all API functions that are likely to
themselves set an error to the current thread, to verify that there is
not error on the current thread when they are called.

Change-Id: I9aadbc4e00d06f3e893970c7c8891dbe7c68606b
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
  • Loading branch information
simark authored and jgalar committed Nov 14, 2019
1 parent d6f6a5a commit 7c7324d
Show file tree
Hide file tree
Showing 32 changed files with 285 additions and 10 deletions.
19 changes: 19 additions & 0 deletions src/lib/assert-pre.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,20 @@
"Index is out of bounds: index=%" PRIu64 ", " \
"count=%" PRIu64, (uint64_t) (_index), (uint64_t) (_length))

/*
* Asserts that the current thread has no error set.
*/
#define BT_ASSERT_PRE_NO_ERROR() \
do { \
const struct bt_error *err = bt_current_thread_take_error(); \
if (err) { \
bt_current_thread_move_error(err); \
} \
BT_ASSERT_PRE(!err, \
"API function called while current thread has an " \
"error: function=%s", __func__); \
} while (0)

#ifdef BT_DEV_MODE
/* Developer mode version of BT_ASSERT_PRE_MSG(). */
# define BT_ASSERT_PRE_DEV_MSG(_fmt, ...) \
Expand Down Expand Up @@ -146,6 +160,10 @@
# define BT_ASSERT_PRE_DEV_VALID_INDEX(_index, _length) \
BT_ASSERT_PRE_VALID_INDEX((_index), (_length))

/* Developer mode version of BT_ASSERT_PRE_NO_ERROR(). */
# define BT_ASSERT_PRE_DEV_NO_ERROR() \
BT_ASSERT_PRE_NO_ERROR()

/*
* Marks a function as being only used within a BT_ASSERT_PRE_DEV()
* context.
Expand All @@ -160,6 +178,7 @@
((void) sizeof((void) (_obj), (void) (_obj_name), 0))
# define BT_ASSERT_PRE_DEV_VALID_INDEX(_index, _length) \
((void) sizeof((void) (_index), (void) (_length), 0))
# define BT_ASSERT_PRE_DEV_NO_ERROR()
# define BT_ASSERT_PRE_DEV_FUNC __attribute__((unused))
#endif /* BT_DEV_MODE */

Expand Down
2 changes: 2 additions & 0 deletions src/lib/graph/component-class-sink-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ struct bt_component_class_sink *bt_component_class_sink_simple_borrow(void)
{
enum bt_component_class_set_method_status set_method_status;

BT_ASSERT_PRE_NO_ERROR();

if (simple_comp_cls) {
goto end;
}
Expand Down
30 changes: 30 additions & 0 deletions src/lib/graph/component-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ struct bt_component_class_source *bt_component_class_source_create(
struct bt_component_class_source *source_class = NULL;
int ret;

BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(name, "Name");
BT_ASSERT_PRE_NON_NULL(method, "Message iterator next method");
BT_LOGI("Creating source component class: "
Expand Down Expand Up @@ -191,6 +192,7 @@ struct bt_component_class_filter *bt_component_class_filter_create(
struct bt_component_class_filter *filter_class = NULL;
int ret;

BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(name, "Name");
BT_ASSERT_PRE_NON_NULL(method, "Message iterator next method");
BT_LOGI("Creating filter component class: "
Expand Down Expand Up @@ -229,6 +231,7 @@ struct bt_component_class_sink *bt_component_class_sink_create(
struct bt_component_class_sink *sink_class = NULL;
int ret;

BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(name, "Name");
BT_ASSERT_PRE_NON_NULL(method, "Consume next method");
BT_LOGI("Creating sink component class: "
Expand Down Expand Up @@ -266,6 +269,7 @@ bt_component_class_source_set_get_supported_mip_versions_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_get_supported_mip_versions_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -280,6 +284,7 @@ bt_component_class_filter_set_get_supported_mip_versions_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_get_supported_mip_versions_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -294,6 +299,7 @@ bt_component_class_sink_set_get_supported_mip_versions_method(
struct bt_component_class_sink *comp_cls,
bt_component_class_sink_get_supported_mip_versions_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -308,6 +314,7 @@ bt_component_class_source_set_initialize_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_initialize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -322,6 +329,7 @@ bt_component_class_filter_set_initialize_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_initialize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -336,6 +344,7 @@ bt_component_class_sink_set_initialize_method(
struct bt_component_class_sink *comp_cls,
bt_component_class_sink_initialize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -350,6 +359,7 @@ bt_component_class_source_set_finalize_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_finalize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -364,6 +374,7 @@ bt_component_class_filter_set_finalize_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_finalize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -378,6 +389,7 @@ bt_component_class_sink_set_finalize_method(
struct bt_component_class_sink *comp_cls,
bt_component_class_sink_finalize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -392,6 +404,7 @@ bt_component_class_source_set_query_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_query_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -406,6 +419,7 @@ bt_component_class_filter_set_query_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_query_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -420,6 +434,7 @@ bt_component_class_sink_set_query_method(
struct bt_component_class_sink *comp_cls,
bt_component_class_sink_query_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -434,6 +449,7 @@ bt_component_class_filter_set_input_port_connected_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_input_port_connected_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -448,6 +464,7 @@ bt_component_class_sink_set_input_port_connected_method(
struct bt_component_class_sink *comp_cls,
bt_component_class_sink_input_port_connected_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -462,6 +479,7 @@ bt_component_class_source_set_output_port_connected_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_output_port_connected_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -476,6 +494,7 @@ bt_component_class_filter_set_output_port_connected_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_output_port_connected_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -490,6 +509,7 @@ bt_component_class_sink_set_graph_is_configured_method(
struct bt_component_class_sink *comp_cls,
bt_component_class_sink_graph_is_configured_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -504,6 +524,7 @@ bt_component_class_source_set_message_iterator_initialize_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_message_iterator_initialize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -518,6 +539,7 @@ bt_component_class_filter_set_message_iterator_initialize_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_message_iterator_initialize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -532,6 +554,7 @@ bt_component_class_source_set_message_iterator_finalize_method(
struct bt_component_class_source *comp_cls,
bt_component_class_source_message_iterator_finalize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -546,6 +569,7 @@ bt_component_class_filter_set_message_iterator_finalize_method(
struct bt_component_class_filter *comp_cls,
bt_component_class_filter_message_iterator_finalize_method method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(method, "Method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -561,6 +585,7 @@ bt_component_class_filter_set_message_iterator_seek_ns_from_origin_methods(
bt_component_class_filter_message_iterator_seek_ns_from_origin_method seek_method,
bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method can_seek_method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(seek_method, "Seek method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -577,6 +602,7 @@ bt_component_class_source_set_message_iterator_seek_ns_from_origin_methods(
bt_component_class_source_message_iterator_seek_ns_from_origin_method seek_method,
bt_component_class_source_message_iterator_can_seek_ns_from_origin_method can_seek_method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(seek_method, "Seek method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -593,6 +619,7 @@ bt_component_class_filter_set_message_iterator_seek_beginning_methods(
bt_component_class_filter_message_iterator_seek_beginning_method seek_method,
bt_component_class_filter_message_iterator_can_seek_beginning_method can_seek_method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(seek_method, "Seek method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -609,6 +636,7 @@ bt_component_class_source_set_message_iterator_seek_beginning_methods(
bt_component_class_source_message_iterator_seek_beginning_method seek_method,
bt_component_class_source_message_iterator_can_seek_beginning_method can_seek_method)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(seek_method, "Seek method");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -624,6 +652,7 @@ bt_component_class_set_description(
struct bt_component_class *comp_cls,
const char *description)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(description, "Description");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand All @@ -640,6 +669,7 @@ enum bt_component_class_set_help_status bt_component_class_set_help(
struct bt_component_class *comp_cls,
const char *help)
{
BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE_NON_NULL(help, "Help");
BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls);
Expand Down
5 changes: 5 additions & 0 deletions src/lib/graph/component-descriptor-set.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct bt_component_descriptor_set *bt_component_descriptor_set_create(void)
{
struct bt_component_descriptor_set *comp_descr_set;

BT_ASSERT_PRE_NO_ERROR();

BT_LOGI_STR("Creating component descriptor set object.");
comp_descr_set = g_new0(struct bt_component_descriptor_set, 1);
if (!comp_descr_set) {
Expand Down Expand Up @@ -140,6 +142,7 @@ bt_component_descriptor_set_add_descriptor_with_initialize_method_data(
struct bt_component_descriptor_set_entry *entry = NULL;
GPtrArray *comp_descr_array = NULL;

BT_ASSERT_PRE_NO_ERROR();
BT_ASSERT_PRE_NON_NULL(comp_descr_set, "Component descriptor set");
BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class");
BT_ASSERT_PRE(!params || bt_value_is_map(params),
Expand Down Expand Up @@ -214,6 +217,8 @@ bt_component_descriptor_set_add_descriptor(
const struct bt_component_class *comp_cls,
const struct bt_value *params)
{
BT_ASSERT_PRE_NO_ERROR();

return bt_component_descriptor_set_add_descriptor_with_initialize_method_data(
comp_descr_set, comp_cls, params, NULL);
}
Expand Down
6 changes: 6 additions & 0 deletions src/lib/graph/component-filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ struct bt_component *bt_component_filter_create(
{
struct bt_component_filter *filter = NULL;

BT_ASSERT_PRE_NO_ERROR();

filter = g_new0(struct bt_component_filter, 1);
if (!filter) {
BT_LIB_LOGE_APPEND_CAUSE(
Expand Down Expand Up @@ -122,6 +124,8 @@ enum bt_self_component_add_port_status bt_self_component_filter_add_output_port(
enum bt_self_component_add_port_status status;
struct bt_port *port = NULL;

BT_ASSERT_PRE_NO_ERROR();

/* bt_component_add_output_port() logs details and errors */
status = bt_component_add_output_port(comp, name, user_data, &port);
if (status != BT_FUNC_STATUS_OK) {
Expand Down Expand Up @@ -190,6 +194,8 @@ enum bt_self_component_add_port_status bt_self_component_filter_add_input_port(
struct bt_port *port = NULL;
struct bt_component *comp = (void *) self_comp;

BT_ASSERT_PRE_NO_ERROR();

/* bt_component_add_input_port() logs details/errors */
status = bt_component_add_input_port(comp, name, user_data, &port);
if (status != BT_FUNC_STATUS_OK) {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/graph/component-sink.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct bt_component *bt_component_sink_create(
{
struct bt_component_sink *sink = NULL;

BT_ASSERT_PRE_NO_ERROR();

sink = g_new0(struct bt_component_sink, 1);
if (!sink) {
BT_LIB_LOGE_APPEND_CAUSE(
Expand Down Expand Up @@ -126,6 +128,8 @@ enum bt_self_component_add_port_status bt_self_component_sink_add_input_port(
struct bt_port *port = NULL;
struct bt_component *comp = (void *) self_comp;

BT_ASSERT_PRE_NO_ERROR();

/* bt_component_add_input_port() logs details/errors */
status = bt_component_add_input_port(comp, name, user_data, &port);
if (status != BT_FUNC_STATUS_OK) {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/graph/component-source.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ struct bt_component *bt_component_source_create(
{
struct bt_component_source *source = NULL;

BT_ASSERT_PRE_NO_ERROR();

source = g_new0(struct bt_component_source, 1);
if (!source) {
BT_LIB_LOGE_APPEND_CAUSE(
Expand Down Expand Up @@ -120,6 +122,8 @@ enum bt_self_component_add_port_status bt_self_component_source_add_output_port(
enum bt_self_component_add_port_status status;
struct bt_port *port = NULL;

BT_ASSERT_PRE_NO_ERROR();

/* bt_component_add_output_port() logs details and errors */
status = bt_component_add_output_port(comp, name, user_data, &port);
if (status != BT_FUNC_STATUS_OK) {
Expand Down
Loading

0 comments on commit 7c7324d

Please sign in to comment.