return 0;
}
+/*
+ * Protocol for LTTNG_UST_ABI_CONTEXT command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - send: var len ctx_name
+ * - receive: struct ustcomm_ust_reply
+ *
+ * TODO: At the next breaking protocol bump, we should indicate the total
+ * command message length as part of a message header so that the protocol can
+ * recover from invalid command errors.
+ */
int lttng_ust_ctl_add_context(int sock, struct lttng_ust_context_attr *ctx,
struct lttng_ust_abi_object_data *obj_data,
struct lttng_ust_abi_object_data **_context_data)
ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
if (ret < 0) {
goto end;
+ } else if (ret == -EINVAL) {
+ /*
+ * Command unknown from remote end. The communication socket is
+ * now out-of-sync and needs to be shutdown.
+ */
+ (void) ustcomm_shutdown_unix_sock(sock);
}
+
context_data->handle = -1;
DBG("Context created successfully");
*_context_data = context_data;
return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_FILTER command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - send: var len bytecode
+ * - receive: struct ustcomm_ust_reply
+ *
+ * TODO: At the next breaking protocol bump, we should indicate the total
+ * command message length as part of a message header so that the protocol can
+ * recover from invalid command errors.
+ */
int lttng_ust_ctl_set_filter(int sock, struct lttng_ust_abi_filter_bytecode *bytecode,
struct lttng_ust_abi_object_data *obj_data)
{
}
if (ret != bytecode->len)
return -EINVAL;
- return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+ ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+ if (ret == -EINVAL) {
+ /*
+ * Command unknown from remote end. The communication socket is
+ * now out-of-sync and needs to be shutdown.
+ */
+ (void) ustcomm_shutdown_unix_sock(sock);
+ }
+ return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_CAPTURE command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - receive: struct ustcomm_ust_reply
+ * - send: var len bytecode
+ * - receive: struct ustcomm_ust_reply (actual command return code)
+ */
int lttng_ust_ctl_set_capture(int sock, struct lttng_ust_abi_capture_bytecode *bytecode,
struct lttng_ust_abi_object_data *obj_data)
{
lum.u.capture.reloc_offset = bytecode->reloc_offset;
lum.u.capture.seqnum = bytecode->seqnum;
- ret = ustcomm_send_app_msg(sock, &lum);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
/* send var len bytecode */
return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
}
+/*
+ * Protocol for LTTNG_UST_ABI_EXCLUSION command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - send: var len exclusion names
+ * - receive: struct ustcomm_ust_reply
+ *
+ * TODO: At the next breaking protocol bump, we should indicate the total
+ * command message length as part of a message header so that the protocol can
+ * recover from invalid command errors.
+ */
int lttng_ust_ctl_set_exclusion(int sock, struct lttng_ust_abi_event_exclusion *exclusion,
struct lttng_ust_abi_object_data *obj_data)
{
if (ret != exclusion->count * LTTNG_UST_ABI_SYM_NAME_LEN) {
return -EINVAL;
}
- return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+ ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+ if (ret == -EINVAL) {
+ /*
+ * Command unknown from remote end. The communication socket is
+ * now out-of-sync and needs to be shutdown.
+ */
+ (void) ustcomm_shutdown_unix_sock(sock);
+ }
+ return ret;
}
/* Enable event, channel and session ioctl */
return lttng_ust_ctl_disable(sock, &obj);
}
+/*
+ * Protocol for LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - receive: struct ustcomm_ust_reply
+ * - send: file descriptor
+ * - receive: struct ustcomm_ust_reply (actual command return code)
+ */
int lttng_ust_ctl_create_event_notifier_group(int sock, int pipe_fd,
struct lttng_ust_abi_object_data **_event_notifier_group_data)
{
lum.handle = LTTNG_UST_ABI_ROOT_HANDLE;
lum.cmd = LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE;
- ret = ustcomm_send_app_msg(sock, &lum);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
goto error;
return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - receive: struct ustcomm_ust_reply
+ * - send: struct lttng_ust_abi_event_notifier
+ * - receive: struct ustcomm_ust_reply (actual command return code)
+ */
int lttng_ust_ctl_create_event_notifier(int sock, struct lttng_ust_abi_event_notifier *event_notifier,
struct lttng_ust_abi_object_data *event_notifier_group,
struct lttng_ust_abi_object_data **_event_notifier_data)
lum.cmd = LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE;
lum.u.event_notifier.len = sizeof(*event_notifier);
- ret = ustcomm_send_app_msg(sock, &lum);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret) {
free(event_notifier_data);
return ret;
return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_CHANNEL command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - send: file descriptors and channel data
+ * - receive: struct ustcomm_ust_reply
+ *
+ * TODO: At the next breaking protocol bump, we should indicate the total
+ * command message length as part of a message header so that the protocol can
+ * recover from invalid command errors.
+ */
int lttng_ust_ctl_send_channel_to_ust(int sock, int session_handle,
struct lttng_ust_abi_object_data *channel_data)
{
ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
if (!ret) {
channel_data->handle = lur.ret_val;
+ } else if (ret == -EINVAL) {
+ /*
+ * Command unknown from remote end. The communication socket is
+ * now out-of-sync and needs to be shutdown.
+ */
+ (void) ustcomm_shutdown_unix_sock(sock);
}
return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_STREAM command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - send: file descriptors and stream data
+ * - receive: struct ustcomm_ust_reply
+ *
+ * TODO: At the next breaking protocol bump, we should indicate the total
+ * command message length as part of a message header so that the protocol can
+ * recover from invalid command errors.
+ */
int lttng_ust_ctl_send_stream_to_ust(int sock,
struct lttng_ust_abi_object_data *channel_data,
struct lttng_ust_abi_object_data *stream_data)
stream_data->u.stream.wakeup_fd, 1);
if (ret)
return ret;
- return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+ ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+ if (ret == -EINVAL) {
+ /*
+ * Command unknown from remote end. The communication socket is
+ * now out-of-sync and needs to be shutdown.
+ */
+ (void) ustcomm_shutdown_unix_sock(sock);
+ }
+ return ret;
}
int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **dest,
free(counter);
}
+/*
+ * Protocol for LTTNG_UST_ABI_COUNTER command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - receive: struct ustcomm_ust_reply
+ * - send: counter data
+ * - receive: struct ustcomm_ust_reply (actual command return code)
+ */
int lttng_ust_ctl_send_counter_data_to_ust(int sock, int parent_handle,
struct lttng_ust_abi_object_data *counter_data)
{
lum.handle = parent_handle;
lum.cmd = LTTNG_UST_ABI_COUNTER;
lum.u.counter.len = size;
- ret = ustcomm_send_app_msg(sock, &lum);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_COUNTER_GLOBAL command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - receive: struct ustcomm_ust_reply
+ * - send: file descriptor
+ * - receive: struct ustcomm_ust_reply (actual command return code)
+ */
int lttng_ust_ctl_send_counter_global_data_to_ust(int sock,
struct lttng_ust_abi_object_data *counter_data,
struct lttng_ust_abi_object_data *counter_global_data)
lum.handle = counter_data->handle; /* parent handle */
lum.cmd = LTTNG_UST_ABI_COUNTER_GLOBAL;
lum.u.counter_global.len = size;
- ret = ustcomm_send_app_msg(sock, &lum);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
return ret;
}
+/*
+ * Protocol for LTTNG_UST_ABI_COUNTER_CPU command:
+ *
+ * - send: struct ustcomm_ust_msg
+ * - receive: struct ustcomm_ust_reply
+ * - send: file descriptor
+ * - receive: struct ustcomm_ust_reply (actual command return code)
+ */
int lttng_ust_ctl_send_counter_cpu_data_to_ust(int sock,
struct lttng_ust_abi_object_data *counter_data,
struct lttng_ust_abi_object_data *counter_cpu_data)
lum.cmd = LTTNG_UST_ABI_COUNTER_CPU;
lum.u.counter_cpu.len = size;
lum.u.counter_cpu.cpu_nr = counter_cpu_data->u.counter_cpu.cpu_nr;
- ret = ustcomm_send_app_msg(sock, &lum);
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret)
return ret;
return ret;
}
+static
+void prepare_cmd_reply(struct ustcomm_ust_reply *lur, uint32_t handle, uint32_t cmd, int ret)
+{
+ lur->handle = handle;
+ lur->cmd = cmd;
+ lur->ret_val = ret;
+ if (ret >= 0) {
+ lur->ret_code = LTTNG_UST_OK;
+ } else {
+ /*
+ * Use -LTTNG_UST_ERR as wildcard for UST internal
+ * error that are not caused by the transport, except if
+ * we already have a more precise error message to
+ * report.
+ */
+ if (ret > -LTTNG_UST_ERR) {
+ /* Translate code to UST error. */
+ switch (ret) {
+ case -EEXIST:
+ lur->ret_code = -LTTNG_UST_ERR_EXIST;
+ break;
+ case -EINVAL:
+ lur->ret_code = -LTTNG_UST_ERR_INVAL;
+ break;
+ case -ENOENT:
+ lur->ret_code = -LTTNG_UST_ERR_NOENT;
+ break;
+ case -EPERM:
+ lur->ret_code = -LTTNG_UST_ERR_PERM;
+ break;
+ case -ENOSYS:
+ lur->ret_code = -LTTNG_UST_ERR_NOSYS;
+ break;
+ default:
+ lur->ret_code = -LTTNG_UST_ERR;
+ break;
+ }
+ } else {
+ lur->ret_code = ret;
+ }
+ }
+}
+
static
int handle_message(struct sock_info *sock_info,
int sock, struct ustcomm_ust_msg *lum)
goto error;
}
+ switch (lum->cmd) {
+ case LTTNG_UST_ABI_FILTER:
+ case LTTNG_UST_ABI_EXCLUSION:
+ case LTTNG_UST_ABI_CHANNEL:
+ case LTTNG_UST_ABI_STREAM:
+ case LTTNG_UST_ABI_CONTEXT:
+ /*
+ * Those commands send additional payload after struct
+ * ustcomm_ust_msg, which makes it pretty much impossible to
+ * deal with "unknown command" errors without leaving the
+ * communication pipe in a out-of-sync state. This is part of
+ * the ABI between liblttng-ust-ctl and liblttng-ust, and
+ * should be fixed on the next breaking
+ * LTTNG_UST_ABI_MAJOR_VERSION protocol bump by indicating the
+ * total command message length as part of a message header so
+ * that the protocol can recover from invalid command errors.
+ */
+ break;
+
+ case LTTNG_UST_ABI_CAPTURE:
+ case LTTNG_UST_ABI_COUNTER:
+ case LTTNG_UST_ABI_COUNTER_GLOBAL:
+ case LTTNG_UST_ABI_COUNTER_CPU:
+ case LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE:
+ case LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE:
+ /*
+ * Those commands expect a reply to the struct ustcomm_ust_msg
+ * before sending additional payload.
+ */
+ prepare_cmd_reply(&lur, lum->handle, lum->cmd, 0);
+
+ ret = send_reply(sock, &lur);
+ if (ret < 0) {
+ DBG("error sending reply");
+ goto error;
+ }
+ break;
+
+ default:
+ /*
+ * Other commands either don't send additional payload, or are
+ * unknown.
+ */
+ break;
+ }
+
switch (lum->cmd) {
case LTTNG_UST_ABI_REGISTER_DONE:
if (lum->handle == LTTNG_UST_ABI_ROOT_HANDLE)
break;
}
- lur.handle = lum->handle;
- lur.cmd = lum->cmd;
- lur.ret_val = ret;
- if (ret >= 0) {
- lur.ret_code = LTTNG_UST_OK;
- } else {
- /*
- * Use -LTTNG_UST_ERR as wildcard for UST internal
- * error that are not caused by the transport, except if
- * we already have a more precise error message to
- * report.
- */
- if (ret > -LTTNG_UST_ERR) {
- /* Translate code to UST error. */
- switch (ret) {
- case -EEXIST:
- lur.ret_code = -LTTNG_UST_ERR_EXIST;
- break;
- case -EINVAL:
- lur.ret_code = -LTTNG_UST_ERR_INVAL;
- break;
- case -ENOENT:
- lur.ret_code = -LTTNG_UST_ERR_NOENT;
- break;
- case -EPERM:
- lur.ret_code = -LTTNG_UST_ERR_PERM;
- break;
- case -ENOSYS:
- lur.ret_code = -LTTNG_UST_ERR_NOSYS;
- break;
- default:
- lur.ret_code = -LTTNG_UST_ERR;
- break;
- }
- } else {
- lur.ret_code = ret;
- }
- }
+ prepare_cmd_reply(&lur, lum->handle, lum->cmd, ret);
+
if (ret >= 0) {
switch (lum->cmd) {
case LTTNG_UST_ABI_TRACER_VERSION: