+cmd_error_code stop_tracing(const lttng::cli::session_spec& spec)
+{
+ bool had_warning = false;
+ bool had_error = false;
+ bool listing_failed = false;
+
+ const auto sessions = [&listing_failed, &spec]() -> lttng::cli::session_list {
+ try {
+ return list_sessions(spec);
+ } catch (const lttng::ctl::error& ctl_exception) {
+ ERR_FMT("Failed to list sessions ({})",
+ lttng_strerror(-ctl_exception.code()));
+ listing_failed = true;
+ return {};
+ } catch (const lttng::cli::no_default_session_error& cli_exception) {
+ /*
+ * The retrieval of the default session name already logs
+ * an error when it fails. There is no value in printing
+ * anything about this exception.
+ */
+ listing_failed = true;
+ return {};
+ }
+ }();
+
+ if (!listing_failed && sessions.size() == 0 &&
+ spec.type_ == lttng::cli::session_spec::type::NAME) {
+ ERR_FMT("Session `{}` not found", spec.value);
+ return CMD_ERROR;
+ }
+
+ if (listing_failed) {
+ return CMD_FATAL;
+ }
+
+ for (const auto& session : sessions) {
+ cmd_error_code sub_ret;
+
+ try {
+ sub_ret = stop_tracing(session.name);
+ } catch (const lttng::ctl::error& ctl_exception) {
+ switch (ctl_exception.code()) {
+ case LTTNG_ERR_TRACE_ALREADY_STOPPED:
+ WARN_FMT("Tracing already stopped for session `{}`", session.name);
+ sub_ret = CMD_SUCCESS;
+ break;
+ case LTTNG_ERR_NO_SESSION:
+ if (spec.type_ != lttng::cli::session_spec::type::NAME) {
+ /* Session destroyed during command, ignore and carry-on. */
+ sub_ret = CMD_SUCCESS;
+ break;
+ } else {
+ sub_ret = CMD_ERROR;
+ break;
+ }
+ case LTTNG_ERR_NO_SESSIOND:
+ /* Don't keep going on a fatal error. */
+ return CMD_FATAL;
+ default:
+ /* Generic error. */
+ sub_ret = CMD_ERROR;
+ ERR_FMT("Failed to stop session `{}` ({})",
+ session.name,
+ lttng_strerror(-ctl_exception.code()));
+ break;
+ }
+ }
+
+ /* Keep going, but report the most serious state. */
+ had_warning |= sub_ret == CMD_WARNING;
+ had_error |= sub_ret == CMD_ERROR;
+ }
+
+ if (had_error) {
+ return CMD_ERROR;
+ } else if (had_warning) {
+ return CMD_WARNING;
+ } else {
+ return CMD_SUCCESS;
+ }