lib: add bt_{graph,query_executor}_add_interrupter()
[babeltrace.git] / src / cli / babeltrace2.c
index 9a631c92b71230e3b84f15f660fd0f7e224d3afa..9699b0c3b5e46fba695fbbf6d4614df0f413f559 100644 (file)
@@ -39,6 +39,7 @@
 #include "babeltrace2-cfg.h"
 #include "babeltrace2-cfg-cli-args.h"
 #include "babeltrace2-cfg-cli-args-default.h"
+#include "babeltrace2-plugins.h"
 
 #define ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH "BABELTRACE_CLI_WARN_COMMAND_NAME_DIRECTORY_CLASH"
 #define ENV_BABELTRACE_CLI_LOG_LEVEL "BABELTRACE_CLI_LOG_LEVEL"
  * modules.
  */
 static const char* log_level_env_var_names[] = {
-       "BABELTRACE_FLT_LTTNG_UTILS_DEBUG_INFO_LOG_LEVEL",
-       "BABELTRACE_FLT_UTILS_COUNTER_LOG_LEVEL",
-       "BABELTRACE_FLT_UTILS_MUXER_LOG_LEVEL",
-       "BABELTRACE_FLT_UTILS_TRIMMER_LOG_LEVEL",
-       "BABELTRACE_PLUGIN_CTF_BFCR_LOG_LEVEL",
        "BABELTRACE_PLUGIN_CTF_METADATA_LOG_LEVEL",
-       "BABELTRACE_PLUGIN_CTF_MSG_ITER_LOG_LEVEL",
-       "BABELTRACE_PLUGIN_CTF_UTILS_LOG_LEVEL",
        "BABELTRACE_PYTHON_BT2_LOG_LEVEL",
-       "BABELTRACE_SINK_CTF_FS_LOG_LEVEL",
-       "BABELTRACE_SINK_TEXT_DETAILS_LOG_LEVEL",
-       "BABELTRACE_SRC_CTF_FS_LOG_LEVEL",
-       "BABELTRACE_SRC_CTF_LTTNG_LIVE_LOG_LEVEL",
-       "BABELTRACE_SRC_TEXT_DMESG_LOG_LEVEL",
        NULL,
 };
 
-/* Application's processing graph (weak) */
-static bt_graph *the_graph;
-static bt_query_executor *the_query_executor;
-static bool canceled = false;
-
-GPtrArray *loaded_plugins;
+/* Application's interrupter (owned by this) */
+static bt_interrupter *the_interrupter;
+static volatile bool interrupted = false;
 
 #ifdef __MINGW32__
 
@@ -79,12 +65,11 @@ GPtrArray *loaded_plugins;
 
 static
 BOOL WINAPI signal_handler(DWORD signal) {
-       if (the_graph) {
-               bt_graph_cancel(the_graph);
+       if (the_interrupter) {
+               bt_interrupter_set(the_interrupter);
        }
 
-       canceled = true;
-
+       interrupted = true;
        return TRUE;
 }
 
@@ -105,15 +90,11 @@ void signal_handler(int signum)
                return;
        }
 
-       if (the_graph) {
-               bt_graph_cancel(the_graph);
+       if (the_interrupter) {
+               bt_interrupter_set(the_interrupter);
        }
 
-       if (the_query_executor) {
-               bt_query_executor_cancel(the_query_executor);
-       }
-
-       canceled = true;
+       interrupted = true;
 }
 
 static
@@ -133,113 +114,91 @@ void set_signal_handler(void)
 
 #endif /* __MINGW32__ */
 
-static
-void init_static_data(void)
-{
-       loaded_plugins = g_ptr_array_new_with_free_func(
-               (GDestroyNotify) bt_object_put_ref);
-}
-
-static
-void fini_static_data(void)
-{
-       g_ptr_array_free(loaded_plugins, TRUE);
-}
-
-static
-int create_the_query_executor(void)
-{
-       int ret = 0;
-
-       the_query_executor = bt_query_executor_create();
-       if (!the_query_executor) {
-               BT_LOGE_STR("Cannot create a query executor.");
-               ret = -1;
-       }
-
-       return ret;
-}
-
-static
-void destroy_the_query_executor(void)
-{
-       BT_QUERY_EXECUTOR_PUT_REF_AND_RESET(the_query_executor);
-}
-
 static
 int query(struct bt_config *cfg, const bt_component_class *comp_cls,
                const char *obj, const bt_value *params,
                const bt_value **user_result, const char **fail_reason)
 {
        const bt_value *result = NULL;
-       bt_query_executor_status status;
+       bt_query_executor_query_status query_status;
+       bt_query_executor *query_exec;
        *fail_reason = "unknown error";
        int ret = 0;
 
        BT_ASSERT(fail_reason);
        BT_ASSERT(user_result);
-       ret = create_the_query_executor();
-       if (ret) {
-               /* create_the_query_executor() logs errors */
-               goto end;
+       query_exec = bt_query_executor_create();
+       if (!query_exec) {
+               BT_CLI_LOGE_APPEND_CAUSE("Cannot create a query executor.");
+               goto error;
        }
 
-       if (canceled) {
-               BT_LOGI("Canceled by user before executing the query: "
+       bt_query_executor_add_interrupter(query_exec, the_interrupter);
+
+       if (interrupted) {
+               BT_CLI_LOGW_APPEND_CAUSE(
+                       "Interrupted by user before executing the query: "
                        "comp-cls-addr=%p, comp-cls-name=\"%s\", "
                        "query-obj=\"%s\"", comp_cls,
                        bt_component_class_get_name(comp_cls), obj);
-               *fail_reason = "canceled by user";
+               *fail_reason = "interrupted by user";
                goto error;
        }
 
        while (true) {
-               status = bt_query_executor_query(the_query_executor,
-                       comp_cls, obj, params, cfg->log_level, &result);
-               switch (status) {
-               case BT_QUERY_EXECUTOR_STATUS_OK:
+               query_status = bt_query_executor_query(
+                       query_exec, comp_cls, obj, params,
+                       cfg->log_level, &result);
+               switch (query_status) {
+               case BT_QUERY_EXECUTOR_QUERY_STATUS_OK:
                        goto ok;
-               case BT_QUERY_EXECUTOR_STATUS_AGAIN:
+               case BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN:
                {
                        const uint64_t sleep_time_us = 100000;
 
+                       if (bt_interrupter_is_set(the_interrupter)) {
+                               *fail_reason = "interrupted by user";
+                               goto error;
+                       }
+
                        /* Wait 100 ms and retry */
-                       BT_LOGD("Got BT_QUERY_EXECUTOR_STATUS_AGAIN: sleeping: "
+                       BT_LOGD("Got BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN: sleeping: "
                                "time-us=%" PRIu64, sleep_time_us);
 
                        if (usleep(sleep_time_us)) {
-                               if (bt_query_executor_is_canceled(the_query_executor)) {
-                                       BT_LOGI("Query was canceled by user: "
+                               if (bt_interrupter_is_set(the_interrupter)) {
+                                       BT_CLI_LOGW_APPEND_CAUSE(
+                                               "Query was interrupted by user: "
                                                "comp-cls-addr=%p, comp-cls-name=\"%s\", "
                                                "query-obj=\"%s\"", comp_cls,
                                                bt_component_class_get_name(comp_cls),
                                                obj);
-                                       *fail_reason = "canceled by user";
+                                       *fail_reason = "interrupted by user";
                                        goto error;
                                }
                        }
 
                        continue;
                }
-               case BT_QUERY_EXECUTOR_STATUS_CANCELED:
-                       *fail_reason = "canceled by user";
-                       goto error;
-               case BT_QUERY_EXECUTOR_STATUS_ERROR:
+               case BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR:
+                       if (bt_interrupter_is_set(the_interrupter)) {
+                               *fail_reason = "interrupted by user";
+                               goto error;
+                       }
+
                        goto error;
-               case BT_QUERY_EXECUTOR_STATUS_INVALID_OBJECT:
+               case BT_QUERY_EXECUTOR_QUERY_STATUS_INVALID_OBJECT:
                        *fail_reason = "invalid or unknown query object";
                        goto error;
-               case BT_QUERY_EXECUTOR_STATUS_INVALID_PARAMS:
+               case BT_QUERY_EXECUTOR_QUERY_STATUS_INVALID_PARAMS:
                        *fail_reason = "invalid query parameters";
                        goto error;
-               case BT_QUERY_EXECUTOR_STATUS_UNSUPPORTED:
-                       *fail_reason = "unsupported action";
-                       goto error;
-               case BT_QUERY_EXECUTOR_STATUS_NOMEM:
+               case BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR:
                        *fail_reason = "not enough memory";
                        goto error;
                default:
-                       BT_LOGF("Unknown query status: status=%d", status);
+                       BT_LOGF("Unknown query status: status=%s",
+                               bt_common_func_status_string(query_status));
                        abort();
                }
        }
@@ -253,40 +212,12 @@ error:
        ret = -1;
 
 end:
-       destroy_the_query_executor();
+       bt_query_executor_put_ref(query_exec);
        bt_value_put_ref(result);
        return ret;
 }
 
-static
-const bt_plugin *find_plugin(const char *name)
-{
-       int i;
-       const bt_plugin *plugin = NULL;
 
-       BT_ASSERT(name);
-       BT_LOGI("Finding plugin: name=\"%s\"", name);
-
-       for (i = 0; i < loaded_plugins->len; i++) {
-               plugin = g_ptr_array_index(loaded_plugins, i);
-
-               if (strcmp(name, bt_plugin_get_name(plugin)) == 0) {
-                       break;
-               }
-
-               plugin = NULL;
-       }
-
-       if (plugin) {
-               BT_LOGI("Found plugin: name=\"%s\", plugin-addr=%p",
-                       name, plugin);
-       } else {
-               BT_LOGI("Cannot find plugin: name=\"%s\"", name);
-       }
-
-       bt_plugin_get_ref(plugin);
-       return plugin;
-}
 
 typedef const void *(*plugin_borrow_comp_cls_func_t)(
                const bt_plugin *, const char *);
@@ -302,7 +233,7 @@ const void *find_component_class_from_plugin(const char *plugin_name,
        BT_LOGI("Finding component class: plugin-name=\"%s\", "
                "comp-cls-name=\"%s\"", plugin_name, comp_class_name);
 
-       plugin = find_plugin(plugin_name);
+       plugin = find_loaded_plugin(plugin_name);
        if (!plugin) {
                goto end;
        }
@@ -410,9 +341,11 @@ void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
        GString *shell_plugin_name = NULL;
        GString *shell_comp_cls_name = NULL;
 
-       shell_plugin_name = bt_common_shell_quote(plugin_name, false);
-       if (!shell_plugin_name) {
-               goto end;
+       if (plugin_name) {
+               shell_plugin_name = bt_common_shell_quote(plugin_name, false);
+               if (!shell_plugin_name) {
+                       goto end;
+               }
        }
 
        shell_comp_cls_name = bt_common_shell_quote(comp_cls_name, false);
@@ -420,14 +353,20 @@ void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
                goto end;
        }
 
-       fprintf(fh, "'%s%s%s%s.%s%s%s.%s%s%s'",
+       fprintf(fh, "'%s%s%s%s",
                bt_common_color_bold(),
                bt_common_color_fg_cyan(),
                component_type_str(type),
-               bt_common_color_fg_default(),
-               bt_common_color_fg_blue(),
-               shell_plugin_name->str,
-               bt_common_color_fg_default(),
+               bt_common_color_fg_default());
+
+       if (shell_plugin_name) {
+               fprintf(fh, ".%s%s%s",
+                       bt_common_color_fg_blue(),
+                       shell_plugin_name->str,
+                       bt_common_color_fg_default());
+       }
+
+       fprintf(fh, ".%s%s%s'",
                bt_common_color_fg_yellow(),
                shell_comp_cls_name->str,
                bt_common_color_reset());
@@ -512,13 +451,13 @@ void print_value_rec(FILE *fp, const bt_value *value, size_t indent)
                        bt_common_color_reset());
                break;
        case BT_VALUE_TYPE_UNSIGNED_INTEGER:
-               uint_val = bt_value_unsigned_integer_get(value);
+               uint_val = bt_value_integer_unsigned_get(value);
                fprintf(fp, "%s%s%" PRIu64 "%s\n", bt_common_color_bold(),
                        bt_common_color_fg_red(), uint_val,
                        bt_common_color_reset());
                break;
        case BT_VALUE_TYPE_SIGNED_INTEGER:
-               int_val = bt_value_signed_integer_get(value);
+               int_val = bt_value_integer_signed_get(value);
                fprintf(fp, "%s%s%" PRId64 "%s\n", bt_common_color_bold(),
                        bt_common_color_fg_red(), int_val,
                        bt_common_color_reset());
@@ -757,131 +696,6 @@ void print_cfg(struct bt_config *cfg)
        }
 }
 
-static
-void add_to_loaded_plugins(const bt_plugin_set *plugin_set)
-{
-       int64_t i;
-       int64_t count;
-
-       count = bt_plugin_set_get_plugin_count(plugin_set);
-       BT_ASSERT(count >= 0);
-
-       for (i = 0; i < count; i++) {
-               const bt_plugin *plugin =
-                       bt_plugin_set_borrow_plugin_by_index_const(plugin_set, i);
-               const bt_plugin *loaded_plugin =
-                       find_plugin(bt_plugin_get_name(plugin));
-
-               BT_ASSERT(plugin);
-
-               if (loaded_plugin) {
-                       BT_LOGI("Not using plugin: another one already exists with the same name: "
-                               "plugin-name=\"%s\", plugin-path=\"%s\", "
-                               "existing-plugin-path=\"%s\"",
-                               bt_plugin_get_name(plugin),
-                               bt_plugin_get_path(plugin),
-                               bt_plugin_get_path(loaded_plugin));
-                       bt_plugin_put_ref(loaded_plugin);
-               } else {
-                       /* Add to global array. */
-                       BT_LOGD("Adding plugin to loaded plugins: plugin-path=\"%s\"",
-                               bt_plugin_get_name(plugin));
-                       bt_plugin_get_ref(plugin);
-                       g_ptr_array_add(loaded_plugins, (void *) plugin);
-               }
-       }
-}
-
-static
-int load_dynamic_plugins(const bt_value *plugin_paths)
-{
-       int nr_paths, i, ret = 0;
-
-       nr_paths = bt_value_array_get_size(plugin_paths);
-       if (nr_paths < 0) {
-               BT_LOGE_STR("Cannot load dynamic plugins: no plugin path.");
-               ret = -1;
-               goto end;
-       }
-
-       BT_LOGI_STR("Loading dynamic plugins.");
-
-       for (i = 0; i < nr_paths; i++) {
-               const bt_value *plugin_path_value = NULL;
-               const char *plugin_path;
-               const bt_plugin_set *plugin_set;
-
-               plugin_path_value =
-                       bt_value_array_borrow_element_by_index_const(
-                               plugin_paths, i);
-               plugin_path = bt_value_string_get(plugin_path_value);
-
-               /*
-                * Skip this if the directory does not exist because
-                * bt_plugin_find_all_from_dir() expects an existing
-                * directory.
-                */
-               if (!g_file_test(plugin_path, G_FILE_TEST_IS_DIR)) {
-                       BT_LOGI("Skipping nonexistent directory path: "
-                               "path=\"%s\"", plugin_path);
-                       continue;
-               }
-
-               plugin_set = bt_plugin_find_all_from_dir(plugin_path, false);
-               if (!plugin_set) {
-                       BT_LOGI("Unable to load dynamic plugins from directory: "
-                               "path=\"%s\"", plugin_path);
-                       continue;
-               }
-
-               add_to_loaded_plugins(plugin_set);
-               bt_plugin_set_put_ref(plugin_set);
-       }
-end:
-       return ret;
-}
-
-static
-int load_static_plugins(void)
-{
-       int ret = 0;
-       const bt_plugin_set *plugin_set;
-
-       BT_LOGI("Loading static plugins.");
-       plugin_set = bt_plugin_find_all_from_static();
-       if (!plugin_set) {
-               BT_LOGE("Unable to load static plugins.");
-               ret = -1;
-               goto end;
-       }
-
-       add_to_loaded_plugins(plugin_set);
-       bt_plugin_set_put_ref(plugin_set);
-end:
-       return ret;
-}
-
-static
-int load_all_plugins(const bt_value *plugin_paths)
-{
-       int ret = 0;
-
-       if (load_dynamic_plugins(plugin_paths)) {
-               ret = -1;
-               goto end;
-       }
-
-       if (load_static_plugins()) {
-               ret = -1;
-               goto end;
-       }
-
-       BT_LOGI("Loaded all plugins: count=%u", loaded_plugins->len);
-
-end:
-       return ret;
-}
-
 static
 void print_plugin_info(const bt_plugin *plugin)
 {
@@ -946,20 +760,12 @@ int cmd_query(struct bt_config *cfg)
                cfg->cmd_data.query.cfg_component->comp_cls_name->str,
                cfg->cmd_data.query.cfg_component->type);
        if (!comp_cls) {
-               BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot find component class: plugin-name=\"%s\", "
                        "comp-cls-name=\"%s\", comp-cls-type=%d",
                        cfg->cmd_data.query.cfg_component->plugin_name->str,
                        cfg->cmd_data.query.cfg_component->comp_cls_name->str,
                        cfg->cmd_data.query.cfg_component->type);
-               fprintf(stderr, "%s%sCannot find component class %s",
-                       bt_common_color_bold(),
-                       bt_common_color_fg_red(),
-                       bt_common_color_reset());
-               print_plugin_comp_cls_opt(stderr,
-                       cfg->cmd_data.query.cfg_component->plugin_name->str,
-                       cfg->cmd_data.query.cfg_component->comp_cls_name->str,
-                       cfg->cmd_data.query.cfg_component->type);
-               fprintf(stderr, "\n");
                ret = -1;
                goto end;
        }
@@ -975,27 +781,14 @@ int cmd_query(struct bt_config *cfg)
        goto end;
 
 failed:
-       BT_LOGE("Failed to query component class: %s: plugin-name=\"%s\", "
+       BT_CLI_LOGE_APPEND_CAUSE(
+               "Failed to query component class: %s: plugin-name=\"%s\", "
                "comp-cls-name=\"%s\", comp-cls-type=%d "
                "object=\"%s\"", fail_reason,
                cfg->cmd_data.query.cfg_component->plugin_name->str,
                cfg->cmd_data.query.cfg_component->comp_cls_name->str,
                cfg->cmd_data.query.cfg_component->type,
                cfg->cmd_data.query.object->str);
-       fprintf(stderr, "%s%sFailed to query info to %s",
-               bt_common_color_bold(),
-               bt_common_color_fg_red(),
-               bt_common_color_reset());
-       print_plugin_comp_cls_opt(stderr,
-               cfg->cmd_data.query.cfg_component->plugin_name->str,
-               cfg->cmd_data.query.cfg_component->comp_cls_name->str,
-               cfg->cmd_data.query.cfg_component->type);
-       fprintf(stderr, "%s%s with object `%s`: %s%s\n",
-               bt_common_color_bold(),
-               bt_common_color_fg_red(),
-               cfg->cmd_data.query.object->str,
-               fail_reason,
-               bt_common_color_reset());
        ret = -1;
 
 end:
@@ -1035,15 +828,11 @@ int cmd_help(struct bt_config *cfg)
        const bt_plugin *plugin = NULL;
        const bt_component_class *needed_comp_cls = NULL;
 
-       plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
+       plugin = find_loaded_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
        if (!plugin) {
-               BT_LOGE("Cannot find plugin: plugin-name=\"%s\"",
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot find plugin: plugin-name=\"%s\"",
                        cfg->cmd_data.help.cfg_component->plugin_name->str);
-               fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
-                       bt_common_color_bold(), bt_common_color_fg_red(),
-                       bt_common_color_fg_blue(),
-                       cfg->cmd_data.help.cfg_component->plugin_name->str,
-                       bt_common_color_reset());
                ret = -1;
                goto end;
        }
@@ -1072,20 +861,12 @@ int cmd_help(struct bt_config *cfg)
                cfg->cmd_data.help.cfg_component->comp_cls_name->str,
                cfg->cmd_data.help.cfg_component->type);
        if (!needed_comp_cls) {
-               BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot find component class: plugin-name=\"%s\", "
                        "comp-cls-name=\"%s\", comp-cls-type=%d",
                        cfg->cmd_data.help.cfg_component->plugin_name->str,
                        cfg->cmd_data.help.cfg_component->comp_cls_name->str,
                        cfg->cmd_data.help.cfg_component->type);
-               fprintf(stderr, "\n%s%sCannot find component class %s",
-                       bt_common_color_bold(),
-                       bt_common_color_fg_red(),
-                       bt_common_color_reset());
-               print_plugin_comp_cls_opt(stderr,
-                       cfg->cmd_data.help.cfg_component->plugin_name->str,
-                       cfg->cmd_data.help.cfg_component->comp_cls_name->str,
-                       cfg->cmd_data.help.cfg_component->type);
-               fprintf(stderr, "\n");
                ret = -1;
                goto end;
        }
@@ -1162,14 +943,14 @@ int cmd_list_plugins(struct bt_config *cfg)
        printf("From the following plugin paths:\n\n");
        print_value(stdout, cfg->plugin_paths, 2);
        printf("\n");
-       plugins_count = loaded_plugins->len;
+       plugins_count = get_loaded_plugins_count();
        if (plugins_count == 0) {
                printf("No plugins found.\n");
                goto end;
        }
 
        for (i = 0; i < plugins_count; i++) {
-               const bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
+               const bt_plugin *plugin = borrow_loaded_plugin(i);
 
                component_classes_count +=
                        bt_plugin_get_source_component_class_count(plugin) +
@@ -1186,7 +967,7 @@ int cmd_list_plugins(struct bt_config *cfg)
                bt_common_color_reset());
 
        for (i = 0; i < plugins_count; i++) {
-               const bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
+               const bt_plugin *plugin = borrow_loaded_plugin(i);
 
                printf("\n");
                print_plugin_info(plugin);
@@ -1235,17 +1016,11 @@ int cmd_print_lttng_live_sessions(struct bt_config *cfg)
        comp_cls = find_component_class(plugin_name, comp_cls_name,
                comp_cls_type);
        if (!comp_cls) {
-               BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot find component class: plugin-name=\"%s\", "
                        "comp-cls-name=\"%s\", comp-cls-type=%d",
                        plugin_name, comp_cls_name,
                        BT_COMPONENT_CLASS_TYPE_SOURCE);
-               fprintf(stderr, "%s%sCannot find component class %s",
-                       bt_common_color_bold(),
-                       bt_common_color_fg_red(),
-                       bt_common_color_reset());
-               print_plugin_comp_cls_opt(stderr, plugin_name,
-                       comp_cls_name, comp_cls_type);
-               fprintf(stderr, "\n");
                goto error;
        }
 
@@ -1269,11 +1044,8 @@ int cmd_print_lttng_live_sessions(struct bt_config *cfg)
        BT_ASSERT(results);
 
        if (!bt_value_is_array(results)) {
-               BT_LOGE_STR("Expecting an array for sessions query.");
-               fprintf(stderr, "%s%sUnexpected type returned by session query%s\n",
-                       bt_common_color_bold(),
-                       bt_common_color_fg_red(),
-                       bt_common_color_reset());
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Expecting an array for LTTng live `sessions` query.");
                goto error;
        }
 
@@ -1286,6 +1058,10 @@ int cmd_print_lttng_live_sessions(struct bt_config *cfg)
                        BT_LOGE_ERRNO("Cannot open file for writing",
                                ": path=\"%s\"",
                                cfg->cmd_data.print_lttng_live_sessions.output_path->str);
+                       (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(
+                               "Babeltrace CLI",
+                               "Cannot open file for writing: path=\"%s\"",
+                               cfg->cmd_data.print_lttng_live_sessions.output_path->str);
                        goto end;
                }
        }
@@ -1297,53 +1073,51 @@ int cmd_print_lttng_live_sessions(struct bt_config *cfg)
 
                map = bt_value_array_borrow_element_by_index_const(results, i);
                if (!map) {
-                       BT_LOGE_STR("Unexpected empty array entry.");
+                       BT_CLI_LOGE_APPEND_CAUSE("Unexpected empty array entry.");
                        goto error;
                }
                if (!bt_value_is_map(map)) {
-                       BT_LOGE_STR("Unexpected entry type.");
+                       BT_CLI_LOGE_APPEND_CAUSE("Unexpected entry type.");
                        goto error;
                }
 
                v = bt_value_map_borrow_entry_value_const(map, "url");
                if (!v) {
-                       BT_LOGE_STR("Unexpected empty array \"url\" entry.");
+                       BT_CLI_LOGE_APPEND_CAUSE("Missing `url` entry.");
                        goto error;
                }
                url_text = bt_value_string_get(v);
                fprintf(out_stream, "%s", url_text);
                v = bt_value_map_borrow_entry_value_const(map, "timer-us");
                if (!v) {
-                       BT_LOGE_STR("Unexpected empty array \"timer-us\" entry.");
+                       BT_CLI_LOGE_APPEND_CAUSE("Missing `timer-us` entry.");
                        goto error;
                }
-               timer_us = bt_value_signed_integer_get(v);
+               timer_us = bt_value_integer_signed_get(v);
                fprintf(out_stream, " (timer = %" PRIu64 ", ", timer_us);
                v = bt_value_map_borrow_entry_value_const(map, "stream-count");
                if (!v) {
-                       BT_LOGE_STR("Unexpected empty array \"stream-count\" entry.");
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Missing `stream-count` entry.");
                        goto error;
                }
-               streams = bt_value_signed_integer_get(v);
+               streams = bt_value_integer_signed_get(v);
                fprintf(out_stream, "%" PRIu64 " stream(s), ", streams);
                v = bt_value_map_borrow_entry_value_const(map, "client-count");
                if (!v) {
-                       BT_LOGE_STR("Unexpected empty array \"client-count\" entry.");
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Missing `client-count` entry.");
                        goto error;
                }
-               clients = bt_value_signed_integer_get(v);
+               clients = bt_value_integer_signed_get(v);
                fprintf(out_stream, "%" PRIu64 " client(s) connected)\n", clients);
        }
 
        goto end;
 
 failed:
-       BT_LOGE("Failed to query for sessions: %s", fail_reason);
-       fprintf(stderr, "%s%sFailed to request sessions: %s%s\n",
-               bt_common_color_bold(),
-               bt_common_color_fg_red(),
-               fail_reason,
-               bt_common_color_reset());
+       BT_CLI_LOGE_APPEND_CAUSE("Failed to query `sessions` object: %s",
+               fail_reason);
 
 error:
        ret = -1;
@@ -1386,17 +1160,11 @@ int cmd_print_ctf_metadata(struct bt_config *cfg)
        comp_cls = find_component_class(plugin_name, comp_cls_name,
                comp_cls_type);
        if (!comp_cls) {
-               BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot find component class: plugin-name=\"%s\", "
                        "comp-cls-name=\"%s\", comp-cls-type=%d",
                        plugin_name, comp_cls_name,
                        BT_COMPONENT_CLASS_TYPE_SOURCE);
-               fprintf(stderr, "%s%sCannot find component class %s",
-                       bt_common_color_bold(),
-                       bt_common_color_fg_red(),
-                       bt_common_color_reset());
-               print_plugin_comp_cls_opt(stderr, plugin_name,
-                       comp_cls_name, comp_cls_type);
-               fprintf(stderr, "\n");
                ret = -1;
                goto end;
        }
@@ -1421,9 +1189,10 @@ int cmd_print_ctf_metadata(struct bt_config *cfg)
        }
 
        metadata_text_value = bt_value_map_borrow_entry_value_const(results,
-                                                                   "text");
+               "text");
        if (!metadata_text_value) {
-               BT_LOGE_STR("Cannot find `text` string value in the resulting metadata info object.");
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot find `text` string value in the resulting metadata info object.");
                ret = -1;
                goto end;
        }
@@ -1435,33 +1204,33 @@ int cmd_print_ctf_metadata(struct bt_config *cfg)
                        fopen(cfg->cmd_data.print_ctf_metadata.output_path->str,
                                "w");
                if (!out_stream) {
-                       ret = -1;
                        BT_LOGE_ERRNO("Cannot open file for writing",
                                ": path=\"%s\"",
                                cfg->cmd_data.print_ctf_metadata.output_path->str);
+                       (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(
+                               "Babeltrace CLI",
+                               "Cannot open file for writing: path=\"%s\"",
+                               cfg->cmd_data.print_ctf_metadata.output_path->str);
+                       ret = -1;
                        goto end;
                }
        }
 
        ret = fprintf(out_stream, "%s\n", metadata_text);
        if (ret < 0) {
-               BT_LOGE("Cannot write whole metadata text to output stream: "
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot write whole metadata text to output stream: "
                        "ret=%d", ret);
                goto end;
        }
 
        ret = 0;
-
        goto end;
 
 failed:
        ret = -1;
-       BT_LOGE("Failed to query for metadata info: %s", fail_reason);
-       fprintf(stderr, "%s%sFailed to request metadata info: %s%s\n",
-               bt_common_color_bold(),
-               bt_common_color_fg_red(),
-               fail_reason,
-               bt_common_color_reset());
+       BT_CLI_LOGE_APPEND_CAUSE(
+               "Failed to query `metadata-info` object: %s", fail_reason);
 
 end:
        bt_value_put_ref(results);
@@ -1508,8 +1277,8 @@ gboolean port_id_equal(gconstpointer v1, gconstpointer v2)
        const struct port_id *id1 = v1;
        const struct port_id *id2 = v2;
 
-       return !strcmp(id1->instance_name, id2->instance_name) &&
-               !strcmp(id1->port_name, id2->port_name);
+       return strcmp(id1->instance_name, id2->instance_name) == 0 &&
+               strcmp(id1->port_name, id2->port_name) == 0;
 }
 
 static
@@ -1619,7 +1388,8 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
        uint64_t i;
        input_port_count_func_t port_count_fn;
        borrow_input_port_by_index_func_t port_by_index_fn;
-       bt_graph_status status = BT_GRAPH_STATUS_ERROR;
+       bt_graph_connect_ports_status connect_ports_status =
+               BT_GRAPH_CONNECT_PORTS_STATUS_OK;
        bool insert_trimmer = false;
        bt_value *trimmer_params = NULL;
        char *intersection_begin = NULL;
@@ -1645,14 +1415,15 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
                range = (struct trace_range *) g_hash_table_lookup(
                        ctx->intersections, &port_id);
                if (range) {
-                       bt_value_status status;
+                       bt_value_map_insert_entry_status insert_status;
 
                        intersection_begin = s_from_ns(
                                range->intersection_range_begin_ns);
                        intersection_end = s_from_ns(
                                range->intersection_range_end_ns);
                        if (!intersection_begin || !intersection_end) {
-                               BT_LOGE_STR("Cannot create trimmer argument timestamp string.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot create trimmer argument timestamp string.");
                                goto error;
                        }
 
@@ -1662,15 +1433,15 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
                                goto error;
                        }
 
-                       status = bt_value_map_insert_string_entry(
+                       insert_status = bt_value_map_insert_string_entry(
                                trimmer_params, "begin", intersection_begin);
-                       if (status != BT_VALUE_STATUS_OK) {
+                       if (insert_status < 0) {
                                goto error;
                        }
-                       status = bt_value_map_insert_string_entry(
+                       insert_status = bt_value_map_insert_string_entry(
                                trimmer_params,
                                "end", intersection_end);
-                       if (status != BT_VALUE_STATUS_OK) {
+                       if (insert_status < 0) {
                                goto error;
                        }
                }
@@ -1707,10 +1478,9 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
        }
 
        if (!downstream_comp) {
-               BT_LOGE("Cannot find downstream component:  comp-name=\"%s\", "
-                       "conn-arg=\"%s\"", cfg_conn->downstream_comp_name->str,
-                       cfg_conn->arg->str);
-               fprintf(stderr, "Cannot create connection: cannot find downstream component: %s\n",
+               BT_CLI_LOGE_APPEND_CAUSE("Cannot find downstream component: "
+                       "comp-name=\"%s\", conn-arg=\"%s\"",
+                       cfg_conn->downstream_comp_name->str,
                        cfg_conn->arg->str);
                goto error;
        }
@@ -1764,7 +1534,7 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
                         * source and the trimmer.
                         */
                        char *trimmer_name = NULL;
-                       bt_graph_status graph_status;
+                       bt_graph_add_component_status add_comp_status;
 
                        ret = asprintf(&trimmer_name,
                                "stream-intersection-trimmer-%s",
@@ -1775,12 +1545,13 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
                        ret = 0;
 
                        ctx->connect_ports = false;
-                       graph_status = bt_graph_add_filter_component(
+                       add_comp_status = bt_graph_add_filter_component(
                                ctx->graph, trimmer_class, trimmer_name,
                                trimmer_params, ctx->cfg->log_level,
                                &trimmer);
                        free(trimmer_name);
-                       if (graph_status != BT_GRAPH_STATUS_OK) {
+                       if (add_comp_status !=
+                                       BT_GRAPH_ADD_COMPONENT_STATUS_OK) {
                                goto error;
                        }
                        BT_ASSERT(trimmer);
@@ -1811,36 +1582,15 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
                }
 
                /* We have a winner! */
-               status = bt_graph_connect_ports(ctx->graph,
+               connect_ports_status = bt_graph_connect_ports(ctx->graph,
                        out_upstream_port, in_downstream_port, NULL);
                downstream_port = NULL;
-               switch (status) {
-               case BT_GRAPH_STATUS_OK:
-                       break;
-               case BT_GRAPH_STATUS_CANCELED:
-                       BT_LOGI_STR("Graph was canceled by user.");
-                       status = BT_GRAPH_STATUS_OK;
-                       break;
-               case BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION:
-                       BT_LOGE("A component refused a connection to one of its ports: "
-                               "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
-                               "upstream-port-addr=%p, upstream-port-name=\"%s\", "
-                               "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
-                               "downstream-port-addr=%p, downstream-port-name=\"%s\", "
-                               "conn-arg=\"%s\"",
-                               upstream_comp, bt_component_get_name(upstream_comp),
-                               upstream_port, bt_port_get_name(upstream_port),
-                               downstream_comp, cfg_conn->downstream_comp_name->str,
-                               downstream_port, downstream_port_name,
-                               cfg_conn->arg->str);
-                       fprintf(stderr,
-                               "A component refused a connection to one of its ports (`%s` to `%s`): %s\n",
-                               bt_port_get_name(upstream_port),
-                               downstream_port_name,
-                               cfg_conn->arg->str);
+               switch (connect_ports_status) {
+               case BT_GRAPH_CONNECT_PORTS_STATUS_OK:
                        break;
                default:
-                       BT_LOGE("Cannot create connection: graph refuses to connect ports: "
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Cannot create connection: graph refuses to connect ports: "
                                "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
                                "upstream-port-addr=%p, upstream-port-name=\"%s\", "
                                "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
@@ -1851,11 +1601,6 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
                                downstream_comp, cfg_conn->downstream_comp_name->str,
                                downstream_port, downstream_port_name,
                                cfg_conn->arg->str);
-                       fprintf(stderr,
-                               "Cannot create connection: graph refuses to connect ports (`%s` to `%s`): %s\n",
-                               bt_port_get_name(upstream_port),
-                               downstream_port_name,
-                               cfg_conn->arg->str);
                        goto error;
                }
 
@@ -1895,15 +1640,13 @@ int cmd_run_ctx_connect_upstream_port_to_downstream_component(
        }
 
        /* No downstream port found */
-       BT_LOGE("Cannot create connection: cannot find a matching downstream port for upstream port: "
+       BT_CLI_LOGE_APPEND_CAUSE(
+               "Cannot create connection: cannot find a matching downstream port for upstream port: "
                "upstream-port-addr=%p, upstream-port-name=\"%s\", "
                "downstream-comp-name=\"%s\", conn-arg=\"%s\"",
                upstream_port, bt_port_get_name(upstream_port),
                cfg_conn->downstream_comp_name->str,
                cfg_conn->arg->str);
-       fprintf(stderr,
-               "Cannot create connection: cannot find a matching downstream port for upstream port `%s`: %s\n",
-               bt_port_get_name(upstream_port), cfg_conn->arg->str);
 
 error:
        ret = -1;
@@ -1934,14 +1677,7 @@ int cmd_run_ctx_connect_upstream_port(struct cmd_run_ctx *ctx,
        BT_ASSERT(upstream_port_name);
        upstream_comp = bt_port_borrow_component_const(
                bt_port_output_as_port_const(upstream_port));
-       if (!upstream_comp) {
-               BT_LOGW("Upstream port to connect is not part of a component: "
-                       "port-addr=%p, port-name=\"%s\"",
-                       upstream_port, upstream_port_name);
-               ret = -1;
-               goto end;
-       }
-
+       BT_ASSERT(upstream_comp);
        upstream_comp_name = bt_component_get_name(upstream_comp);
        BT_ASSERT(upstream_comp_name);
        BT_LOGI("Connecting upstream port: comp-addr=%p, comp-name=\"%s\", "
@@ -1968,26 +1704,20 @@ int cmd_run_ctx_connect_upstream_port(struct cmd_run_ctx *ctx,
                ret = cmd_run_ctx_connect_upstream_port_to_downstream_component(
                        ctx, upstream_comp, upstream_port, cfg_conn);
                if (ret) {
-                       BT_LOGE("Cannot connect upstream port: "
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Cannot connect upstream port: "
                                "port-addr=%p, port-name=\"%s\"",
                                upstream_port,
                                upstream_port_name);
-                       fprintf(stderr,
-                               "Cannot connect port `%s` of component `%s` to a downstream port: %s\n",
-                               upstream_port_name,
-                               upstream_comp_name,
-                               cfg_conn->arg->str);
                        goto error;
                }
                goto end;
        }
 
-       BT_LOGE("Cannot connect upstream port: port does not match any connection argument: "
+       BT_CLI_LOGE_APPEND_CAUSE(
+               "Cannot connect upstream port: port does not match any connection argument: "
                "port-addr=%p, port-name=\"%s\"", upstream_port,
                upstream_port_name);
-       fprintf(stderr,
-               "Cannot create connection: upstream port `%s` does not match any connection\n",
-               upstream_port_name);
 
 error:
        ret = -1;
@@ -1997,13 +1727,14 @@ end:
 }
 
 static
-bt_graph_listener_status
+bt_graph_listener_func_status
 graph_output_port_added_listener(struct cmd_run_ctx *ctx,
                const bt_port_output *out_port)
 {
        const bt_component *comp;
        const bt_port *port = bt_port_output_as_port_const(out_port);
-       bt_graph_listener_status ret = BT_GRAPH_LISTENER_STATUS_OK;
+       bt_graph_listener_func_status ret =
+               BT_GRAPH_LISTENER_FUNC_STATUS_OK;
 
        comp = bt_port_borrow_component_const(port);
        BT_LOGI("Port added to a graph's component: comp-addr=%p, "
@@ -2015,10 +1746,7 @@ graph_output_port_added_listener(struct cmd_run_ctx *ctx,
                goto end;
        }
 
-       if (!comp) {
-               BT_LOGW_STR("Port has no component.");
-               goto end;
-       }
+       BT_ASSERT(comp);
 
        if (bt_port_is_connected(port)) {
                BT_LOGW_STR("Port is already connected.");
@@ -2026,9 +1754,8 @@ graph_output_port_added_listener(struct cmd_run_ctx *ctx,
        }
 
        if (cmd_run_ctx_connect_upstream_port(ctx, out_port)) {
-               BT_LOGF_STR("Cannot connect upstream port.");
-               fprintf(stderr, "Added port could not be connected: aborting\n");
-               ret = BT_GRAPH_LISTENER_STATUS_ERROR;
+               BT_CLI_LOGE_APPEND_CAUSE("Cannot connect upstream port.");
+               ret = BT_GRAPH_LISTENER_FUNC_STATUS_ERROR;
                goto end;
        }
 
@@ -2037,7 +1764,7 @@ end:
 }
 
 static
-bt_graph_listener_status graph_source_output_port_added_listener(
+bt_graph_listener_func_status graph_source_output_port_added_listener(
                const bt_component_source *component,
                const bt_port_output *port, void *data)
 {
@@ -2045,7 +1772,7 @@ bt_graph_listener_status graph_source_output_port_added_listener(
 }
 
 static
-bt_graph_listener_status graph_filter_output_port_added_listener(
+bt_graph_listener_func_status graph_filter_output_port_added_listener(
                const bt_component_filter *component,
                const bt_port_output *port, void *data)
 {
@@ -2080,7 +1807,6 @@ void cmd_run_ctx_destroy(struct cmd_run_ctx *ctx)
        }
 
        BT_GRAPH_PUT_REF_AND_RESET(ctx->graph);
-       the_graph = NULL;
        ctx->cfg = NULL;
 }
 
@@ -2088,7 +1814,7 @@ static
 int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
 {
        int ret = 0;
-       bt_graph_status status;
+       bt_graph_add_listener_status add_listener_status;
 
        ctx->cfg = cfg;
        ctx->connect_ports = false;
@@ -2124,20 +1850,22 @@ int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
                goto error;
        }
 
-       the_graph = ctx->graph;
-       status = bt_graph_add_source_component_output_port_added_listener(
+       bt_graph_add_interrupter(ctx->graph, the_interrupter);
+       add_listener_status = bt_graph_add_source_component_output_port_added_listener(
                ctx->graph, graph_source_output_port_added_listener, NULL, ctx,
                NULL);
-       if (status != BT_GRAPH_STATUS_OK) {
-               BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
+       if (add_listener_status != BT_GRAPH_ADD_LISTENER_STATUS_OK) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot add \"port added\" listener to graph.");
                goto error;
        }
 
-       status = bt_graph_add_filter_component_output_port_added_listener(
+       add_listener_status = bt_graph_add_filter_component_output_port_added_listener(
                ctx->graph, graph_filter_output_port_added_listener, NULL, ctx,
                NULL);
-       if (status != BT_GRAPH_STATUS_OK) {
-               BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
+       if (add_listener_status != BT_GRAPH_ADD_LISTENER_STATUS_OK) {
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot add \"port added\" listener to graph.");
                goto error;
        }
 
@@ -2237,11 +1965,12 @@ int set_stream_intersections(struct cmd_run_ctx *ctx,
                        goto error;
                }
 
-               begin = bt_value_signed_integer_get(intersection_begin);
-               end = bt_value_signed_integer_get(intersection_end);
+               begin = bt_value_integer_signed_get(intersection_begin);
+               end = bt_value_integer_signed_get(intersection_end);
 
                if (begin < 0 || end < 0 || end < begin) {
-                       BT_LOGW("Invalid trace stream intersection values: "
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Invalid trace stream intersection values: "
                                "intersection-range-ns:begin=%" PRId64
                                ", intersection-range-ns:end=%" PRId64,
                                begin, end);
@@ -2269,20 +1998,23 @@ int set_stream_intersections(struct cmd_run_ctx *ctx,
                        port_id = g_new0(struct port_id, 1);
                        if (!port_id) {
                                ret = -1;
-                               BT_LOGE_STR("Cannot allocate memory for port_id structure.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot allocate memory for port_id structure.");
                                goto error;
                        }
                        port_id->instance_name = strdup(cfg_comp->instance_name->str);
                        if (!port_id->instance_name) {
                                ret = -1;
-                               BT_LOGE_STR("Cannot allocate memory for port_id component instance name.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot allocate memory for port_id component instance name.");
                                goto error;
                        }
 
                        trace_range = g_new0(struct trace_range, 1);
                        if (!trace_range) {
                                ret = -1;
-                               BT_LOGE_STR("Cannot allocate memory for trace_range structure.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot allocate memory for trace_range structure.");
                                goto error;
                        }
                        trace_range->intersection_range_begin_ns = begin;
@@ -2292,21 +2024,24 @@ int set_stream_intersections(struct cmd_run_ctx *ctx,
                                stream_infos, stream_idx);
                        if (!stream_info || !bt_value_is_map(stream_info)) {
                                ret = -1;
-                               BT_LOGE_STR("Cannot retrieve stream informations from trace in query result.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot retrieve stream informations from trace in query result.");
                                goto error;
                        }
 
                        port_name = bt_value_map_borrow_entry_value_const(stream_info, "port-name");
                        if (!port_name || !bt_value_is_string(port_name)) {
                                ret = -1;
-                               BT_LOGE_STR("Cannot retrieve port name in query result.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot retrieve port name in query result.");
                                goto error;
                        }
 
                        port_id->port_name = g_strdup(bt_value_string_get(port_name));
                        if (!port_id->port_name) {
                                ret = -1;
-                               BT_LOGE_STR("Cannot allocate memory for port_id port_name.");
+                               BT_CLI_LOGE_APPEND_CAUSE(
+                                       "Cannot allocate memory for port_id port_name.");
                                goto error;
                        }
 
@@ -2322,11 +2057,10 @@ int set_stream_intersections(struct cmd_run_ctx *ctx,
        goto end;
 
 error:
-       fprintf(stderr, "%s%sCannot determine stream intersection of trace at path \'%s\'.%s\n",
-               bt_common_color_bold(),
-               bt_common_color_fg_yellow(),
-               path ? path : "(unknown)",
-               bt_common_color_reset());
+       BT_CLI_LOGE_APPEND_CAUSE(
+               "Cannot determine stream intersection of trace: path=\"%s\"",
+               path ? path : "(unknown)");
+
 end:
        bt_value_put_ref(query_result);
        g_free(port_id);
@@ -2369,24 +2103,16 @@ int cmd_run_ctx_create_components_from_config_components(
                }
 
                if (!comp_cls) {
-                       BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Cannot find component class: plugin-name=\"%s\", "
                                "comp-cls-name=\"%s\", comp-cls-type=%d",
                                cfg_comp->plugin_name->str,
                                cfg_comp->comp_cls_name->str,
                                cfg_comp->type);
-                       fprintf(stderr, "%s%sCannot find component class %s",
-                               bt_common_color_bold(),
-                               bt_common_color_fg_red(),
-                               bt_common_color_reset());
-                       print_plugin_comp_cls_opt(stderr,
-                               cfg_comp->plugin_name->str,
-                               cfg_comp->comp_cls_name->str,
-                               cfg_comp->type);
-                       fprintf(stderr, "\n");
                        goto error;
                }
 
-               BT_ASSERT(cfg_comp->log_level >= BT_LOG_VERBOSE);
+               BT_ASSERT(cfg_comp->log_level >= BT_LOG_TRACE);
 
                switch (cfg_comp->type) {
                case BT_COMPONENT_CLASS_TYPE_SOURCE:
@@ -2412,17 +2138,13 @@ int cmd_run_ctx_create_components_from_config_components(
                }
 
                if (ret) {
-                       BT_LOGE("Cannot create component: plugin-name=\"%s\", "
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Cannot create component: plugin-name=\"%s\", "
                                "comp-cls-name=\"%s\", comp-cls-type=%d, "
                                "comp-name=\"%s\"",
                                cfg_comp->plugin_name->str,
                                cfg_comp->comp_cls_name->str,
                                cfg_comp->type, cfg_comp->instance_name->str);
-                       fprintf(stderr, "%s%sCannot create component `%s`%s\n",
-                               bt_common_color_bold(),
-                               bt_common_color_fg_red(),
-                               cfg_comp->instance_name->str,
-                               bt_common_color_reset());
                        goto error;
                }
 
@@ -2576,29 +2298,6 @@ end:
        return ret;
 }
 
-static inline
-const char *bt_graph_status_str(bt_graph_status status)
-{
-       switch (status) {
-       case BT_GRAPH_STATUS_OK:
-               return "BT_GRAPH_STATUS_OK";
-       case BT_GRAPH_STATUS_END:
-               return "BT_GRAPH_STATUS_END";
-       case BT_GRAPH_STATUS_AGAIN:
-               return "BT_GRAPH_STATUS_AGAIN";
-       case BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION:
-               return "BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION";
-       case BT_GRAPH_STATUS_CANCELED:
-               return "BT_GRAPH_STATUS_CANCELED";
-       case BT_GRAPH_STATUS_ERROR:
-               return "BT_GRAPH_STATUS_ERROR";
-       case BT_GRAPH_STATUS_NOMEM:
-               return "BT_GRAPH_STATUS_NOMEM";
-       default:
-               return "(unknown)";
-       }
-}
-
 static
 int cmd_run(struct bt_config *cfg)
 {
@@ -2607,13 +2306,14 @@ int cmd_run(struct bt_config *cfg)
 
        /* Initialize the command's context and the graph object */
        if (cmd_run_ctx_init(&ctx, cfg)) {
-               BT_LOGE_STR("Cannot initialize the command's context.");
-               fprintf(stderr, "Cannot initialize the command's context\n");
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot initialize the command's context.");
                goto error;
        }
 
-       if (canceled) {
-               BT_LOGI_STR("Canceled by user before creating components.");
+       if (interrupted) {
+               BT_CLI_LOGW_APPEND_CAUSE(
+                       "Interrupted by user before creating components.");
                goto error;
        }
 
@@ -2621,13 +2321,13 @@ int cmd_run(struct bt_config *cfg)
 
        /* Create the requested component instances */
        if (cmd_run_ctx_create_components(&ctx)) {
-               BT_LOGE_STR("Cannot create components.");
-               fprintf(stderr, "Cannot create components\n");
+               BT_CLI_LOGE_APPEND_CAUSE("Cannot create components.");
                goto error;
        }
 
-       if (canceled) {
-               BT_LOGI_STR("Canceled by user before connecting components.");
+       if (interrupted) {
+               BT_CLI_LOGW_APPEND_CAUSE(
+                       "Interrupted by user before connecting components.");
                goto error;
        }
 
@@ -2635,13 +2335,14 @@ int cmd_run(struct bt_config *cfg)
 
        /* Connect the initially visible component ports */
        if (cmd_run_ctx_connect_ports(&ctx)) {
-               BT_LOGE_STR("Cannot connect initial component ports.");
-               fprintf(stderr, "Cannot connect initial component ports\n");
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Cannot connect initial component ports.");
                goto error;
        }
 
-       if (canceled) {
-               BT_LOGI_STR("Canceled by user before running the graph.");
+       if (interrupted) {
+               BT_CLI_LOGW_APPEND_CAUSE(
+                       "Interrupted by user before running the graph.");
                goto error;
        }
 
@@ -2649,7 +2350,7 @@ int cmd_run(struct bt_config *cfg)
 
        /* Run the graph */
        while (true) {
-               bt_graph_status graph_status = bt_graph_run(ctx.graph);
+               bt_graph_run_status run_status = bt_graph_run(ctx.graph);
 
                /*
                 * Reset console in case something messed with console
@@ -2658,39 +2359,46 @@ int cmd_run(struct bt_config *cfg)
                printf("%s", bt_common_color_reset());
                fflush(stdout);
                fprintf(stderr, "%s", bt_common_color_reset());
-               BT_LOGV("bt_graph_run() returned: status=%s",
-                       bt_graph_status_str(graph_status));
+               BT_LOGT("bt_graph_run() returned: status=%s",
+                       bt_common_func_status_string(run_status));
 
-               switch (graph_status) {
-               case BT_GRAPH_STATUS_OK:
+               switch (run_status) {
+               case BT_GRAPH_RUN_STATUS_OK:
                        break;
-               case BT_GRAPH_STATUS_CANCELED:
-                       BT_LOGI_STR("Graph was canceled by user.");
-                       goto error;
-               case BT_GRAPH_STATUS_AGAIN:
-                       if (bt_graph_is_canceled(ctx.graph)) {
-                               BT_LOGI_STR("Graph was canceled by user.");
+               case BT_GRAPH_RUN_STATUS_AGAIN:
+                       if (bt_interrupter_is_set(the_interrupter)) {
+                               BT_CLI_LOGW_APPEND_CAUSE(
+                                       "Graph was interrupted by user.");
                                goto error;
                        }
 
                        if (cfg->cmd_data.run.retry_duration_us > 0) {
-                               BT_LOGV("Got BT_GRAPH_STATUS_AGAIN: sleeping: "
+                               BT_LOGT("Got BT_GRAPH_RUN_STATUS_AGAIN: sleeping: "
                                        "time-us=%" PRIu64,
                                        cfg->cmd_data.run.retry_duration_us);
 
                                if (usleep(cfg->cmd_data.run.retry_duration_us)) {
-                                       if (bt_graph_is_canceled(ctx.graph)) {
-                                               BT_LOGI_STR("Graph was canceled by user.");
+                                       if (bt_interrupter_is_set(the_interrupter)) {
+                                               BT_CLI_LOGW_APPEND_CAUSE(
+                                                       "Graph was interrupted by user.");
                                                goto error;
                                        }
                                }
                        }
                        break;
-               case BT_GRAPH_STATUS_END:
+               case BT_GRAPH_RUN_STATUS_END:
                        goto end;
                default:
-                       BT_LOGE_STR("Graph failed to complete successfully");
-                       fprintf(stderr, "Graph failed to complete successfully\n");
+                       if (bt_interrupter_is_set(the_interrupter)) {
+                               BT_CLI_LOGW_APPEND_CAUSE(
+                                       "Graph was interrupted by user and failed: "
+                                       "status=%s",
+                                       bt_common_func_status_string(run_status));
+                               goto error;
+                       }
+
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Graph failed to complete successfully");
                        goto error;
                }
        }
@@ -2723,13 +2431,14 @@ void warn_command_name_and_directory_clash(struct bt_config *cfg)
 
        if (g_file_test(cfg->command_name,
                        G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
-               fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
-                       cfg->command_name);
-               fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
-                       cfg->command_name);
-               fprintf(stderr, "\n");
-               fprintf(stderr, "    babeltrace2 convert %s [OPTIONS]\n",
-                       cfg->command_name);
+               _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__,
+                               BT_LOG_WARNING, BT_LOG_TAG,
+                               "The `%s` command was executed. "
+                               "If you meant to convert a trace located in "
+                               "the local `%s` directory, please use:\n\n"
+                               "    babeltrace2 convert %s [OPTIONS]",
+                               cfg->command_name, cfg->command_name,
+                               cfg->command_name);
        }
 }
 
@@ -2751,7 +2460,7 @@ void set_auto_log_levels(struct bt_config *cfg)
         */
        if (getenv("BABELTRACE_DEBUG") &&
                        strcmp(getenv("BABELTRACE_DEBUG"), "1") == 0) {
-               cfg->log_level = BT_LOG_VERBOSE;
+               cfg->log_level = BT_LOG_TRACE;
        } else if (getenv("BABELTRACE_VERBOSE") &&
                        strcmp(getenv("BABELTRACE_VERBOSE"), "1") == 0) {
                cfg->log_level = BT_LOG_INFO;
@@ -2763,15 +2472,15 @@ void set_auto_log_levels(struct bt_config *cfg)
         * --verbose. So:
         *
         *     --verbose: INFO log level
-        *     --debug:   VERBOSE log level (includes DEBUG, which is
-        *                is less verbose than VERBOSE in the internal
+        *     --debug:   TRACE log level (includes DEBUG, which is
+        *                is less verbose than TRACE in the internal
         *                logging framework)
         */
-       if (!getenv("BABELTRACE_LOGGING_GLOBAL_LEVEL")) {
+       if (!getenv("LIBBABELTRACE2_INIT_LOG_LEVEL")) {
                if (cfg->verbose) {
                        bt_logging_set_global_level(BT_LOG_INFO);
                } else if (cfg->debug) {
-                       bt_logging_set_global_level(BT_LOG_VERBOSE);
+                       bt_logging_set_global_level(BT_LOG_TRACE);
                } else {
                        /*
                         * Set library's default log level if not
@@ -2785,7 +2494,7 @@ void set_auto_log_levels(struct bt_config *cfg)
                if (cfg->verbose) {
                        bt_cli_log_level = BT_LOG_INFO;
                } else if (cfg->debug) {
-                       bt_cli_log_level = BT_LOG_VERBOSE;
+                       bt_cli_log_level = BT_LOG_TRACE;
                } else {
                        /*
                         * Set CLI's default log level if not explicitly
@@ -2800,9 +2509,9 @@ void set_auto_log_levels(struct bt_config *cfg)
        while (*env_var_name) {
                if (!getenv(*env_var_name)) {
                        if (cfg->verbose) {
-                               g_setenv(*env_var_name, "I", 1);
+                               g_setenv(*env_var_name, "INFO", 1);
                        } else if (cfg->debug) {
-                               g_setenv(*env_var_name, "V", 1);
+                               g_setenv(*env_var_name, "TRACE", 1);
                        } else {
                                char val[2] = { 0 };
 
@@ -2820,6 +2529,123 @@ void set_auto_log_levels(struct bt_config *cfg)
        }
 }
 
+static
+void print_error_causes(void)
+{
+       const bt_error *error = bt_current_thread_take_error();
+       int64_t i;
+       GString *folded = NULL;
+       unsigned int columns;
+
+       if (!error || bt_error_get_cause_count(error) == 0) {
+               fprintf(stderr, "%s%sUnknown command-line error.%s\n",
+                       bt_common_color_bold(), bt_common_color_fg_red(),
+                       bt_common_color_reset());
+               goto end;
+       }
+
+       /* Try to get terminal width to fold the error cause messages */
+       if (bt_common_get_term_size(&columns, NULL) < 0) {
+               /* Width not found: default to 80 */
+               columns = 80;
+       }
+
+       /*
+        * This helps visually separate the error causes from the last
+        * logging statement.
+        */
+       fprintf(stderr, "\n");
+
+       /* Reverse order: deepest (root) cause printed at the end */
+       for (i = bt_error_get_cause_count(error) - 1; i >= 0; i--) {
+               const bt_error_cause *cause =
+                       bt_error_borrow_cause_by_index(error, (uint64_t) i);
+               const char *prefix_fmt =
+                       i == bt_error_get_cause_count(error) - 1 ?
+                               "%s%sERROR%s:    " : "%s%sCAUSED BY%s ";
+
+               /* Print prefix */
+               fprintf(stderr, prefix_fmt,
+                       bt_common_color_bold(), bt_common_color_fg_red(),
+                       bt_common_color_reset());
+
+               /* Print actor name */
+               fprintf(stderr, "[");
+               switch (bt_error_cause_get_actor_type(cause)) {
+               case BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN:
+                       fprintf(stderr, "%s%s%s",
+                               bt_common_color_bold(),
+                               bt_error_cause_get_module_name(cause),
+                               bt_common_color_reset());
+                       break;
+               case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT:
+                       fprintf(stderr, "%s%s%s: ",
+                               bt_common_color_bold(),
+                               bt_error_cause_component_actor_get_component_name(cause),
+                               bt_common_color_reset());
+                       print_plugin_comp_cls_opt(stderr,
+                               bt_error_cause_component_actor_get_plugin_name(cause),
+                               bt_error_cause_component_actor_get_component_class_name(cause),
+                               bt_error_cause_component_actor_get_component_class_type(cause));
+                       break;
+               case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS:
+                       print_plugin_comp_cls_opt(stderr,
+                               bt_error_cause_component_class_actor_get_plugin_name(cause),
+                               bt_error_cause_component_class_actor_get_component_class_name(cause),
+                               bt_error_cause_component_class_actor_get_component_class_type(cause));
+                       break;
+               case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR:
+                       fprintf(stderr, "%s%s%s (%s%s%s): ",
+                               bt_common_color_bold(),
+                               bt_error_cause_message_iterator_actor_get_component_name(cause),
+                               bt_common_color_reset(),
+                               bt_common_color_bold(),
+                               bt_error_cause_message_iterator_actor_get_component_output_port_name(cause),
+                               bt_common_color_reset());
+                       print_plugin_comp_cls_opt(stderr,
+                               bt_error_cause_message_iterator_actor_get_plugin_name(cause),
+                               bt_error_cause_message_iterator_actor_get_component_class_name(cause),
+                               bt_error_cause_message_iterator_actor_get_component_class_type(cause));
+                       break;
+               default:
+                       abort();
+               }
+
+               /* Print file name and line number */
+               fprintf(stderr, "] (%s%s%s%s:%s%" PRIu64 "%s)\n",
+                       bt_common_color_bold(),
+                       bt_common_color_fg_magenta(),
+                       bt_error_cause_get_file_name(cause),
+                       bt_common_color_reset(),
+                       bt_common_color_fg_green(),
+                       bt_error_cause_get_line_number(cause),
+                       bt_common_color_reset());
+
+               /* Print message */
+               folded = bt_common_fold(bt_error_cause_get_message(cause),
+                       columns, 2);
+               if (!folded) {
+                       BT_LOGE_STR("Could not fold string.");
+                       fprintf(stderr, "%s\n",
+                               bt_error_cause_get_message(cause));
+                       continue;
+               }
+
+               fprintf(stderr, "%s\n", folded->str);
+               g_string_free(folded, TRUE);
+               folded = NULL;
+       }
+
+end:
+       if (folded) {
+               g_string_free(folded, TRUE);
+       }
+
+       if (error) {
+               bt_error_release(error);
+       }
+}
+
 int main(int argc, const char **argv)
 {
        int ret;
@@ -2828,7 +2654,7 @@ int main(int argc, const char **argv)
 
        init_log_level();
        set_signal_handler();
-       init_static_data();
+       init_loaded_plugins();
        cfg = bt_config_cli_args_create_with_default(argc, argv, &retcode);
 
        if (retcode < 0) {
@@ -2839,13 +2665,14 @@ int main(int argc, const char **argv)
        }
 
        if (retcode > 0) {
-               BT_LOGE("Command-line error: retcode=%d", retcode);
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Command-line error: retcode=%d", retcode);
                goto end;
        }
 
        if (!cfg) {
-               BT_LOGE_STR("Failed to create a valid Babeltrace configuration.");
-               fprintf(stderr, "Failed to create Babeltrace configuration\n");
+               BT_CLI_LOGE_APPEND_CAUSE(
+                       "Failed to create a valid Babeltrace configuration.");
                retcode = 1;
                goto end;
        }
@@ -2854,14 +2681,23 @@ int main(int argc, const char **argv)
        print_cfg(cfg);
 
        if (cfg->command_needs_plugins) {
-               ret = load_all_plugins(cfg->plugin_paths);
+               ret = require_loaded_plugins(cfg->plugin_paths);
                if (ret) {
-                       BT_LOGE("Failed to load plugins: ret=%d", ret);
+                       BT_CLI_LOGE_APPEND_CAUSE(
+                               "Failed to load plugins: ret=%d", ret);
                        retcode = 1;
                        goto end;
                }
        }
 
+       BT_ASSERT(!the_interrupter);
+       the_interrupter = bt_interrupter_create();
+       if (!the_interrupter) {
+               BT_CLI_LOGE_APPEND_CAUSE("Failed to create an interrupter object.");
+               retcode = 1;
+               goto end;
+       }
+
        BT_LOGI("Executing command: cmd=%d, command-name=\"%s\"",
                cfg->command, cfg->command_name);
 
@@ -2896,6 +2732,17 @@ int main(int argc, const char **argv)
 
 end:
        BT_OBJECT_PUT_REF_AND_RESET(cfg);
-       fini_static_data();
+       fini_loaded_plugins();
+       bt_interrupter_put_ref(the_interrupter);
+
+       if (retcode != 0) {
+               print_error_causes();
+       }
+
+       /*
+        * Clear current thread's error in case there is one to avoid a
+        * memory leak.
+        */
+       bt_current_thread_clear_error();
        return retcode;
 }
This page took 0.045897 seconds and 4 git commands to generate.