#include "utils.h"
#include "manage-consumer.h"
#include "clear.h"
+#include "agent-thread.h"
static bool is_root;
return ret;
}
+static enum lttng_error_code receive_lttng_trigger(struct command_ctx *cmd_ctx,
+ int sock,
+ int *sock_error,
+ struct lttng_trigger **_trigger)
+{
+ int ret;
+ size_t trigger_len;
+ ssize_t sock_recv_len;
+ enum lttng_error_code ret_code;
+ struct lttng_payload trigger_payload;
+ struct lttng_trigger *trigger = NULL;
+
+ lttng_payload_init(&trigger_payload);
+ trigger_len = (size_t) cmd_ctx->lsm.u.trigger.length;
+ ret = lttng_dynamic_buffer_set_size(
+ &trigger_payload.buffer, trigger_len);
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ sock_recv_len = lttcomm_recv_unix_sock(
+ sock, trigger_payload.buffer.data, trigger_len);
+ if (sock_recv_len < 0 || sock_recv_len != trigger_len) {
+ ERR("Failed to receive trigger in command payload");
+ *sock_error = 1;
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ /* Receive fds, if any. */
+ if (cmd_ctx->lsm.fd_count > 0) {
+ sock_recv_len = lttcomm_recv_payload_fds_unix_sock(
+ sock, cmd_ctx->lsm.fd_count, &trigger_payload);
+ if (sock_recv_len > 0 &&
+ sock_recv_len != cmd_ctx->lsm.fd_count * sizeof(int)) {
+ ERR("Failed to receive all file descriptors for trigger in command payload: expected fd count = %u, ret = %d",
+ cmd_ctx->lsm.fd_count, (int) ret);
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ *sock_error = 1;
+ goto end;
+ } else if (sock_recv_len <= 0) {
+ ERR("Failed to receive file descriptors for trigger in command payload: expected fd count = %u, ret = %d",
+ cmd_ctx->lsm.fd_count, (int) ret);
+ ret_code = LTTNG_ERR_FATAL;
+ *sock_error = 1;
+ goto end;
+ }
+ }
+
+ /* Deserialize trigger. */
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &trigger_payload, 0, -1);
+
+ if (lttng_trigger_create_from_payload(&view, &trigger) !=
+ trigger_len) {
+ ERR("Invalid trigger received as part of command payload");
+ ret_code = LTTNG_ERR_INVALID_TRIGGER;
+ lttng_trigger_put(trigger);
+ goto end;
+ }
+ }
+
+ *_trigger = trigger;
+ ret_code = LTTNG_OK;
+
+end:
+ return ret_code;
+}
+
/*
* Version of setup_lttng_msg() without command header.
*/
int *sock_error)
{
int ret = LTTNG_OK;
- int need_tracing_session = 1;
- int need_domain;
+ bool need_tracing_session = true;
+ bool need_domain;
+ bool need_consumerd;
- DBG("Processing client command %d", cmd_ctx->lsm.cmd_type);
+ DBG("Processing client command '%s\' (%d)",
+ lttcomm_sessiond_command_str(cmd_ctx->lsm.cmd_type),
+ cmd_ctx->lsm.cmd_type);
assert(!rcu_read_ongoing());
case LTTNG_SET_SESSION_SHM_PATH:
case LTTNG_REGENERATE_METADATA:
case LTTNG_REGENERATE_STATEDUMP:
- case LTTNG_REGISTER_TRIGGER:
- case LTTNG_UNREGISTER_TRIGGER:
case LTTNG_ROTATE_SESSION:
case LTTNG_ROTATION_GET_INFO:
case LTTNG_ROTATION_SET_SCHEDULE:
case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
case LTTNG_CLEAR_SESSION:
- need_domain = 0;
+ case LTTNG_LIST_TRIGGERS:
+ need_domain = false;
+ break;
+ default:
+ need_domain = true;
+ }
+
+ /* Needs a functioning consumerd? */
+ switch (cmd_ctx->lsm.cmd_type) {
+ case LTTNG_REGISTER_TRIGGER:
+ case LTTNG_UNREGISTER_TRIGGER:
+ need_consumerd = false;
break;
default:
- need_domain = 1;
+ need_consumerd = true;
+ break;
}
if (config.no_kernel && need_domain
case LTTNG_DATA_PENDING:
case LTTNG_ROTATE_SESSION:
case LTTNG_ROTATION_GET_INFO:
+ case LTTNG_REGISTER_TRIGGER:
+ case LTTNG_LIST_TRIGGERS:
break;
default:
/* Setup lttng message with no payload */
case LTTNG_SAVE_SESSION:
case LTTNG_REGISTER_TRIGGER:
case LTTNG_UNREGISTER_TRIGGER:
- need_tracing_session = 0;
+ case LTTNG_LIST_TRIGGERS:
+ need_tracing_session = false;
break;
default:
DBG("Getting session %s by name", cmd_ctx->lsm.session.name);
}
/* Consumer is in an ERROR state. Report back to client */
- if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) {
+ if (need_consumerd && uatomic_read(&kernel_consumerd_state) ==
+ CONSUMER_ERROR) {
ret = LTTNG_ERR_NO_KERNCONSUMERD;
goto error;
}
case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_LOG4J:
case LTTNG_DOMAIN_PYTHON:
+ if (!agent_tracing_is_enabled()) {
+ ret = LTTNG_ERR_AGENT_TRACING_DISABLED;
+ goto error;
+ }
+ /* Fallthrough */
case LTTNG_DOMAIN_UST:
{
if (!ust_app_supported()) {
ret = LTTNG_ERR_NO_UST;
goto error;
}
+
/* Consumer is in an ERROR state. Report back to client */
- if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) {
+ if (need_consumerd && uatomic_read(&ust_consumerd_state) ==
+ CONSUMER_ERROR) {
ret = LTTNG_ERR_NO_USTCONSUMERD;
goto error;
}
}
case LTTNG_REGISTER_TRIGGER:
{
+ struct lttng_trigger *payload_trigger;
struct lttng_trigger *return_trigger;
- size_t original_payload_size;
- size_t payload_size;
+ size_t original_reply_payload_size;
+ size_t reply_payload_size;
+ const struct lttng_credentials cmd_creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid),
+ .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid),
+ };
ret = setup_empty_lttng_msg(cmd_ctx);
if (ret) {
goto setup_error;
}
- original_payload_size = cmd_ctx->reply_payload.buffer.size;
+ ret = receive_lttng_trigger(
+ cmd_ctx, *sock, sock_error, &payload_trigger);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ original_reply_payload_size = cmd_ctx->reply_payload.buffer.size;
- ret = cmd_register_trigger(cmd_ctx, *sock,
+ ret = cmd_register_trigger(&cmd_creds, payload_trigger,
notification_thread_handle, &return_trigger);
if (ret != LTTNG_OK) {
+ lttng_trigger_put(payload_trigger);
goto error;
}
ret = lttng_trigger_serialize(return_trigger, &cmd_ctx->reply_payload);
+ lttng_trigger_put(payload_trigger);
+ lttng_trigger_put(return_trigger);
if (ret) {
ERR("Failed to serialize trigger in reply to \"register trigger\" command");
ret = LTTNG_ERR_NOMEM;
- lttng_trigger_destroy(return_trigger);
goto error;
}
- lttng_trigger_destroy(return_trigger);
- return_trigger = NULL;
-
- payload_size = cmd_ctx->reply_payload.buffer.size -
- original_payload_size;
+ reply_payload_size = cmd_ctx->reply_payload.buffer.size -
+ original_reply_payload_size;
- update_lttng_msg(cmd_ctx, 0, payload_size);
+ update_lttng_msg(cmd_ctx, 0, reply_payload_size);
ret = LTTNG_OK;
break;
}
case LTTNG_UNREGISTER_TRIGGER:
{
- ret = cmd_unregister_trigger(cmd_ctx, *sock,
+ struct lttng_trigger *payload_trigger;
+ const struct lttng_credentials cmd_creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid),
+ .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid),
+ };
+
+ ret = receive_lttng_trigger(
+ cmd_ctx, *sock, sock_error, &payload_trigger);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ ret = cmd_unregister_trigger(&cmd_creds, payload_trigger,
notification_thread_handle);
+ lttng_trigger_put(payload_trigger);
break;
}
case LTTNG_ROTATE_SESSION:
ret = cmd_clear_session(cmd_ctx->session, sock);
break;
}
+ case LTTNG_LIST_TRIGGERS:
+ {
+ struct lttng_triggers *return_triggers = NULL;
+ size_t original_payload_size;
+ size_t payload_size;
+
+ ret = setup_empty_lttng_msg(cmd_ctx);
+ if (ret) {
+ ret = LTTNG_ERR_NOMEM;
+ goto setup_error;
+ }
+
+ original_payload_size = cmd_ctx->reply_payload.buffer.size;
+
+ ret = cmd_list_triggers(cmd_ctx,
+ notification_thread_handle, &return_triggers);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ assert(return_triggers);
+ ret = lttng_triggers_serialize(
+ return_triggers, &cmd_ctx->reply_payload);
+ lttng_triggers_destroy(return_triggers);
+ if (ret) {
+ ERR("Failed to serialize triggers in reply to `list triggers` command");
+ ret = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ payload_size = cmd_ctx->reply_payload.buffer.size -
+ original_payload_size;
+
+ update_lttng_msg(cmd_ctx, 0, payload_size);
+
+ ret = LTTNG_OK;
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
continue;
}
+ if (ret < LTTNG_OK || ret >= LTTNG_ERR_NR) {
+ WARN("Command returned an invalid status code, returning unknown error: command type = %d, ret = %d", cmd_ctx.lsm.cmd_type, ret);
+ ret = LTTNG_ERR_UNK;
+ }
+
cmd_completion_handler = cmd_pop_completion_handler();
if (cmd_completion_handler) {
enum lttng_error_code completion_code;
struct lttcomm_lttng_msg *llm = (typeof(
llm)) cmd_ctx.reply_payload.buffer.data;
- assert(cmd_ctx.reply_payload.buffer.size >=
- sizeof(llm));
+ assert(cmd_ctx.reply_payload.buffer.size >= sizeof(*llm));
assert(cmd_ctx.lttng_msg_size == cmd_ctx.reply_payload.buffer.size);
llm->fd_count = lttng_payload_view_get_fd_handle_count(&view);