From: Philippe Proulx Date: Sat, 13 May 2017 01:14:11 +0000 (-0400) Subject: babeltrace(1): handle SIGINT to cancel the graph gracefully X-Git-Tag: v2.0.0-pre1~275 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=5401f7805580b24f88459d94c901c8f1184877a1 babeltrace(1): handle SIGINT to cancel the graph gracefully It goes like this: 1. Ctrl+C 2. SIGINT 3. sigint_handler() 4. Cancel the application's graph. 5. bt_graph_run() eventually returns BT_GRAPH_STATUS_CANCELED or   BT_GRAPH_STATUS_AGAIN. 6. When we get those statuses, we check if the graph is canceled and quit the loop if so. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- diff --git a/cli/babeltrace.c b/cli/babeltrace.c index 03d65891..4f1f8b1f 100644 --- a/cli/babeltrace.c +++ b/cli/babeltrace.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "babeltrace-cfg.h" #include "babeltrace-cfg-cli-args.h" #include "babeltrace-cfg-cli-args-default.h" @@ -58,11 +59,29 @@ #define ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH "BABELTRACE_CLI_WARN_COMMAND_NAME_DIRECTORY_CLASH" +/* Application's processing graph (weak) */ +static struct bt_graph *the_graph; +static bool canceled = false; + GPtrArray *loaded_plugins; BT_HIDDEN int bt_cli_log_level = BT_LOG_NONE; +static +void sigint_handler(int signum) +{ + if (signum != SIGINT) { + return; + } + + if (the_graph) { + bt_graph_cancel(the_graph); + } + + canceled = true; +} + static void init_static_data(void) { @@ -1326,6 +1345,7 @@ void cmd_run_ctx_destroy(struct cmd_run_ctx *ctx) } BT_PUT(ctx->graph); + the_graph = NULL; ctx->cfg = NULL; } @@ -1347,6 +1367,7 @@ int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg) goto error; } + the_graph = ctx->graph; ret = bt_graph_add_port_added_listener(ctx->graph, graph_port_added_listener, ctx); if (ret) { @@ -1581,6 +1602,10 @@ int cmd_run(struct bt_config *cfg) goto error; } + if (canceled) { + goto end; + } + BT_LOGI_STR("Running the graph."); /* Run the graph */ @@ -1590,7 +1615,17 @@ int cmd_run(struct bt_config *cfg) switch (graph_status) { case BT_GRAPH_STATUS_OK: break; + case BT_GRAPH_STATUS_CANCELED: + BT_LOGI("Graph was canceled by user: status=%d", + graph_status); + goto error; case BT_GRAPH_STATUS_AGAIN: + if (bt_graph_is_canceled(ctx.graph)) { + BT_LOGI("Graph was canceled by user: status=%d", + graph_status); + goto error; + } + if (cfg->cmd_data.run.retry_duration_us > 0) { BT_LOGV("Got BT_GRAPH_STATUS_AGAIN: sleeping: " "time-us=%" PRIu64, @@ -1678,6 +1713,20 @@ set_level: bt_cli_log_level = log_level; } +void set_sigint_handler(void) +{ + struct sigaction new_action, old_action; + + new_action.sa_handler = sigint_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + sigaction(SIGINT, NULL, &old_action); + + if (old_action.sa_handler != SIG_IGN) { + sigaction(SIGINT, &new_action, NULL); + } +} + int main(int argc, const char **argv) { int ret; @@ -1685,6 +1734,7 @@ int main(int argc, const char **argv) struct bt_config *cfg; init_log_level(); + set_sigint_handler(); init_static_data(); cfg = bt_config_cli_args_create_with_default(argc, argv, &retcode); diff --git a/lib/graph/graph.c b/lib/graph/graph.c index 808296f7..ab6b14cf 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -588,11 +588,6 @@ enum bt_graph_status bt_graph_run(struct bt_graph *graph) } do { - if (graph->canceled) { - status = BT_GRAPH_STATUS_CANCELED; - goto end; - } - status = bt_graph_consume(graph); if (status == BT_GRAPH_STATUS_AGAIN) { /*