#include <stdint.h>
#include <lttng/ust-compiler.h>
-#define LTTNG_UST_SYM_NAME_LEN 256
+#ifndef __ust_stringify
+#define __ust_stringify1(x) #x
+#define __ust_stringify(x) __ust_stringify1(x)
+#endif /* __ust_stringify */
-/* Version for comm protocol between sessiond and ust */
-#define LTTNG_UST_COMM_VERSION_MAJOR 2
-#define LTTNG_UST_COMM_VERSION_MINOR 1
+#define LTTNG_UST_SYM_NAME_LEN 256
+#define LTTNG_UST_ABI_PROCNAME_LEN 16
+
+/* UST comm magic number, used to validate protocol and endianness. */
+#define LTTNG_UST_COMM_MAGIC 0xC57C57C5
/* Version for ABI between liblttng-ust, sessiond, consumerd */
-#define LTTNG_UST_INTERNAL_MAJOR_VERSION 3
-#define LTTNG_UST_INTERNAL_MINOR_VERSION 0
-#define LTTNG_UST_INTERNAL_PATCHLEVEL_VERSION 0
+#define LTTNG_UST_ABI_MAJOR_VERSION 4
+#define LTTNG_UST_ABI_MINOR_VERSION 0
enum lttng_ust_instrumentation {
LTTNG_UST_TRACEPOINT = 0,
LTTNG_UST_OBJECT_TYPE_UNKNOWN = -1,
LTTNG_UST_OBJECT_TYPE_CHANNEL = 0,
LTTNG_UST_OBJECT_TYPE_STREAM = 1,
+ LTTNG_UST_OBJECT_TYPE_EVENT = 2,
+ LTTNG_UST_OBJECT_TYPE_CONTEXT = 3,
};
#define LTTNG_UST_OBJECT_DATA_PADDING1 32
#define _LTTNG_UST_CTL_H
#include <lttng/ust-abi.h>
-
-#ifndef LTTNG_PACKED
-#define LTTNG_PACKED __attribute__((packed))
-#endif
+#include <sys/types.h>
#ifndef LTTNG_UST_UUID_LEN
#define LTTNG_UST_UUID_LEN 16
#endif
+/* Default unix socket path */
+#define LTTNG_UST_SOCK_FILENAME \
+ "lttng-ust-sock-" \
+ __ust_stringify(LTTNG_UST_ABI_MAJOR_VERSION)
+
+/*
+ * Shared memory files path are automatically related to shm root, e.g.
+ * /dev/shm under linux.
+ */
+#define LTTNG_UST_WAIT_FILENAME \
+ "lttng-ust-wait-" \
+ __ust_stringify(LTTNG_UST_ABI_MAJOR_VERSION)
+
struct lttng_ust_shm_handle;
struct lttng_ust_lib_ring_buffer;
void ustctl_flush_buffer(struct ustctl_consumer_stream *stream,
int producer_active);
+/* event registry management */
+
+enum ustctl_socket_type {
+ USTCTL_SOCKET_CMD = 0,
+ USTCTL_SOCKET_NOTIFY = 1,
+};
+
+enum ustctl_notify_cmd {
+ USTCTL_NOTIFY_CMD_EVENT = 0,
+ USTCTL_NOTIFY_CMD_CHANNEL = 1,
+};
+
+enum ustctl_channel_header {
+ USTCTL_CHANNEL_HEADER_UNKNOWN = 0,
+ USTCTL_CHANNEL_HEADER_COMPACT = 1,
+ USTCTL_CHANNEL_HEADER_LARGE = 2,
+};
+
+/* event type structures */
+
+enum ustctl_abstract_types {
+ ustctl_atype_integer,
+ ustctl_atype_enum,
+ ustctl_atype_array,
+ ustctl_atype_sequence,
+ ustctl_atype_string,
+ ustctl_atype_float,
+ NR_USTCTL_ABSTRACT_TYPES,
+};
+
+enum ustctl_string_encodings {
+ ustctl_encode_none = 0,
+ ustctl_encode_UTF8 = 1,
+ ustctl_encode_ASCII = 2,
+ NR_USTCTL_STRING_ENCODINGS,
+};
+
+#define USTCTL_UST_INTEGER_TYPE_PADDING 24
+struct ustctl_integer_type {
+ uint32_t size; /* in bits */
+ uint32_t signedness;
+ uint32_t reverse_byte_order;
+ uint32_t base; /* 2, 8, 10, 16, for pretty print */
+ enum ustctl_string_encodings encoding;
+ uint16_t alignment; /* in bits */
+ char padding[USTCTL_UST_INTEGER_TYPE_PADDING];
+} LTTNG_PACKED;
+
+#define USTCTL_UST_FLOAT_TYPE_PADDING 24
+struct ustctl_float_type {
+ uint32_t exp_dig; /* exponent digits, in bits */
+ uint32_t mant_dig; /* mantissa digits, in bits */
+ uint32_t reverse_byte_order;
+ uint16_t alignment; /* in bits */
+ char padding[USTCTL_UST_FLOAT_TYPE_PADDING];
+} LTTNG_PACKED;
+
+#define USTCTL_UST_BASIC_TYPE_PADDING 296
+union _ustctl_basic_type {
+ struct ustctl_integer_type integer;
+ struct {
+ enum ustctl_string_encodings encoding;
+ } string;
+ struct ustctl_float_type _float;
+ char padding[USTCTL_UST_BASIC_TYPE_PADDING];
+} LTTNG_PACKED;
+
+struct ustctl_basic_type {
+ enum ustctl_abstract_types atype;
+ union {
+ union _ustctl_basic_type basic;
+ } u;
+} LTTNG_PACKED;
+
+#define USTCTL_UST_TYPE_PADDING 128
+struct ustctl_type {
+ enum ustctl_abstract_types atype;
+ union {
+ union _ustctl_basic_type basic;
+ struct {
+ struct ustctl_basic_type elem_type;
+ uint32_t length; /* num. elems. */
+ } array;
+ struct {
+ struct ustctl_basic_type length_type;
+ struct ustctl_basic_type elem_type;
+ } sequence;
+ char padding[USTCTL_UST_TYPE_PADDING];
+ } u;
+} LTTNG_PACKED;
+
+#define USTCTL_UST_FIELD_PADDING 28
+struct ustctl_field {
+ char name[LTTNG_UST_SYM_NAME_LEN];
+ struct ustctl_type type;
+ char padding[USTCTL_UST_FIELD_PADDING];
+} LTTNG_PACKED;
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * If an error other than -LTTNG_UST_ERR_UNSUP_MAJOR is returned,
+ * the output fields are not populated.
+ */
+int ustctl_recv_reg_msg(int sock,
+ enum ustctl_socket_type *type,
+ uint32_t *major,
+ uint32_t *minor,
+ uint32_t *pid,
+ uint32_t *ppid,
+ uint32_t *uid,
+ uint32_t *gid,
+ uint32_t *bits_per_long,
+ uint32_t *uint8_t_alignment,
+ uint32_t *uint16_t_alignment,
+ uint32_t *uint32_t_alignment,
+ uint32_t *uint64_t_alignment,
+ uint32_t *long_alignment,
+ int *byte_order,
+ char *name); /* size LTTNG_UST_ABI_PROCNAME_LEN */
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ * Receive the notification command. The "notify_cmd" can then be used
+ * by the caller to find out which ustctl_recv_* function should be
+ * called to receive the notification, and which ustctl_reply_* is
+ * appropriate.
+ */
+int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd);
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int ustctl_recv_register_event(int sock,
+ int *session_objd, /* session descriptor (output) */
+ int *channel_objd, /* channel descriptor (output) */
+ char *event_name, /*
+ * event name (output,
+ * size LTTNG_UST_SYM_NAME_LEN)
+ */
+ int *loglevel,
+ char **signature, /*
+ * event signature
+ * (output, dynamically
+ * allocated, must be free(3)'d
+ * by the caller if function
+ * returns success.)
+ */
+ size_t *nr_fields,
+ struct ustctl_field **fields,
+ char **model_emf_uri);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_register_event(int sock,
+ uint32_t id, /* event id (input) */
+ int ret_code); /* return code. 0 ok, negative error */
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int ustctl_recv_register_channel(int sock,
+ int *session_objd, /* session descriptor (output) */
+ int *channel_objd, /* channel descriptor (output) */
+ size_t *nr_fields, /* context fields */
+ struct ustctl_field **fields);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_register_channel(int sock,
+ uint32_t chan_id,
+ enum ustctl_channel_header header_type,
+ int ret_code); /* return code. 0 ok, negative error */
+
#endif /* _LTTNG_UST_CTL_H */
LTTNG_UST_ERR_NOSYS = 1029, /* Not implemented */
LTTNG_UST_ERR_EXITING = 1030, /* Process is exiting */
+ LTTNG_UST_ERR_INVAL_MAGIC = 1031, /* Invalid magic number */
+ LTTNG_UST_ERR_INVAL_SOCKET_TYPE = 1032, /* Invalid socket type */
+ LTTNG_UST_ERR_UNSUP_MAJOR = 1033, /* Unsupported major version */
+
/* MUST be last element */
LTTNG_UST_ERR_NR, /* Last element */
};
/* Event ID management */
struct lttng_session *session;
int objd; /* Object associated to channel */
- unsigned int free_event_id; /* Next event ID to allocate */
- unsigned int used_event_id; /* Max allocated event IDs */
+ unsigned int _deprecated1;
+ unsigned int _deprecated2;
struct cds_list_head node; /* Channel list in session */
const struct lttng_channel_ops *ops;
int header_type; /* 0: unset, 1: compact, 2: large */
struct cds_list_head events_head; /* list of events */
struct cds_list_head _deprecated1;
struct cds_list_head node; /* Session list */
- unsigned int free_chan_id; /* Next chan ID to allocate */
+ int _deprecated2;
unsigned int metadata_dumped:1;
/* New UST 2.1 */
/* List of enablers */
struct cds_list_head enablers_head;
struct lttng_ust_event_ht events_ht; /* ht of events */
+ void *owner; /* object owner */
};
struct lttng_transport {
*/
#define LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS 3000
-#define LTTNG_RUNDIR "/var/run/lttng"
-#define LTTNG_HOME_RUNDIR "%s/.lttng"
-
-/* Default unix socket path */
-#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK LTTNG_RUNDIR "/client-lttng-sessiond"
-#define DEFAULT_GLOBAL_APPS_UNIX_SOCK LTTNG_RUNDIR "/apps-lttng-sessiond"
-#define DEFAULT_HOME_APPS_UNIX_SOCK LTTNG_HOME_RUNDIR "/apps-lttng-sessiond"
-#define DEFAULT_HOME_CLIENT_UNIX_SOCK LTTNG_HOME_RUNDIR "/client-lttng-sessiond"
-
-#define DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH "/lttng-ust-apps-wait"
-#define DEFAULT_HOME_APPS_WAIT_SHM_PATH "/lttng-ust-apps-wait-%u"
+#define LTTNG_DEFAULT_RUNDIR "/var/run/lttng"
+#define LTTNG_DEFAULT_HOME_RUNDIR ".lttng"
/* Queue size of listen(2) */
-#define LTTNG_UST_COMM_MAX_LISTEN 10
+#define LTTNG_UST_COMM_MAX_LISTEN 10
+#define LTTNG_UST_COMM_REG_MSG_PADDING 64
+
+struct lttng_event_field;
+
+struct ustctl_reg_msg {
+ uint32_t magic;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t pid;
+ uint32_t ppid;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t bits_per_long;
+ uint32_t uint8_t_alignment;
+ uint32_t uint16_t_alignment;
+ uint32_t uint32_t_alignment;
+ uint32_t uint64_t_alignment;
+ uint32_t long_alignment;
+ uint32_t socket_type; /* enum ustctl_socket_type */
+ char name[LTTNG_UST_ABI_PROCNAME_LEN]; /* process name */
+ char padding[LTTNG_UST_COMM_REG_MSG_PADDING];
+} LTTNG_PACKED;
/*
* Data structure for the commands sent from sessiond to UST.
*/
+#define USTCOMM_MSG_PADDING1 32
+#define USTCOMM_MSG_PADDING2 32
struct ustcomm_ust_msg {
uint32_t handle;
uint32_t cmd;
+ char padding[USTCOMM_MSG_PADDING1];
union {
struct lttng_ust_channel channel;
struct lttng_ust_stream stream;
uint32_t reloc_offset;
uint64_t seqnum;
} LTTNG_PACKED filter;
+ char padding[USTCOMM_MSG_PADDING2];
} u;
} LTTNG_PACKED;
* Data structure for the response from UST to the session daemon.
* cmd_type is sent back in the reply for validation.
*/
+#define USTCOMM_REPLY_PADDING1 32
+#define USTCOMM_REPLY_PADDING2 32
struct ustcomm_ust_reply {
uint32_t handle;
uint32_t cmd;
- uint32_t ret_code; /* enum enum ustcomm_return_code */
+ uint32_t ret_code; /* enum ustcomm_return_code */
uint32_t ret_val; /* return value */
+ char padding[USTCOMM_REPLY_PADDING1];
union {
struct {
uint64_t memory_map_size;
} LTTNG_PACKED stream;
struct lttng_ust_tracer_version version;
struct lttng_ust_tracepoint_iter tracepoint;
+ char padding[USTCOMM_REPLY_PADDING2];
} u;
} LTTNG_PACKED;
+struct ustcomm_notify_hdr {
+ uint32_t notify_cmd;
+} LTTNG_PACKED;
+
+#define USTCOMM_NOTIFY_EVENT_MSG_PADDING 32
+struct ustcomm_notify_event_msg {
+ uint32_t session_objd;
+ uint32_t channel_objd;
+ char event_name[LTTNG_UST_SYM_NAME_LEN];
+ int32_t loglevel;
+ uint32_t signature_len;
+ uint32_t fields_len;
+ uint32_t model_emf_uri_len;
+ char padding[USTCOMM_NOTIFY_EVENT_MSG_PADDING];
+ /* followed by signature, fields, and model_emf_uri */
+} LTTNG_PACKED;
+
+#define USTCOMM_NOTIFY_EVENT_REPLY_PADDING 32
+struct ustcomm_notify_event_reply {
+ int32_t ret_code; /* 0: ok, negative: error code */
+ uint32_t event_id;
+ char padding[USTCOMM_NOTIFY_EVENT_REPLY_PADDING];
+} LTTNG_PACKED;
+
+#define USTCOMM_NOTIFY_CHANNEL_MSG_PADDING 32
+struct ustcomm_notify_channel_msg {
+ uint32_t session_objd;
+ uint32_t channel_objd;
+ uint32_t ctx_fields_len;
+ char padding[USTCOMM_NOTIFY_CHANNEL_MSG_PADDING];
+ /* followed by context fields */
+} LTTNG_PACKED;
+
+#define USTCOMM_NOTIFY_CHANNEL_REPLY_PADDING 32
+struct ustcomm_notify_channel_reply {
+ int32_t ret_code; /* 0: ok, negative: error code */
+ uint32_t chan_id;
+ uint32_t header_type; /* enum ustctl_channel_header */
+ char padding[USTCOMM_NOTIFY_CHANNEL_REPLY_PADDING];
+} LTTNG_PACKED;
+
/*
* LTTNG_UST_TRACEPOINT_FIELD_LIST reply is followed by a
* struct lttng_ust_field_iter field.
extern int ustcomm_close_unix_sock(int sock);
extern ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len);
-extern ssize_t ustcomm_send_unix_sock(int sock, void *buf, size_t len);
+extern ssize_t ustcomm_send_unix_sock(int sock, const void *buf, size_t len);
extern ssize_t ustcomm_send_fds_unix_sock(int sock, int *fds, size_t nb_fd);
extern ssize_t ustcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd);
uint64_t *memory_map_size,
int *shm_fd, int *wakeup_fd);
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_send_reg_msg(int sock,
+ enum ustctl_socket_type type,
+ uint32_t bits_per_long,
+ uint32_t uint8_t_alignment,
+ uint32_t uint16_t_alignment,
+ uint32_t uint32_t_alignment,
+ uint32_t uint64_t_alignment,
+ uint32_t long_alignment);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_event(int sock,
+ int session_objd, /* session descriptor */
+ int channel_objd, /* channel descriptor */
+ const char *event_name, /* event name (input) */
+ int loglevel,
+ const char *signature, /* event signature (input) */
+ size_t nr_fields, /* fields */
+ const struct lttng_event_field *fields,
+ const char *model_emf_uri,
+ uint32_t *id); /* event id (output) */
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_channel(int sock,
+ int session_objd, /* session descriptor */
+ int channel_objd, /* channel descriptor */
+ size_t nr_ctx_fields,
+ const struct lttng_event_field *ctx_fields,
+ uint32_t *chan_id, /* channel id (output) */
+ int *header_type); /* header type (output) */
+
#endif /* _LTTNG_UST_COMM_H */
#include <errno.h>
#include <fcntl.h>
+#include <lttng/ust-ctl.h>
#include <ust-comm.h>
#include <helper.h>
#include <lttng/ust-error.h>
+#include <lttng/ust-events.h>
+#include <usterr-signal-safe.h>
+
+#include "../liblttng-ust/compat.h"
#define USTCOMM_CODE_OFFSET(code) \
(code == LTTNG_UST_OK ? 0 : (code - LTTNG_UST_ERR + 1))
[ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_PERM) ] = "Permission denied",
[ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOSYS) ] = "Not implemented",
[ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_EXITING) ] = "Process is exiting",
+
+ [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_MAGIC) ] = "Invalid magic number",
+ [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_SOCKET_TYPE) ] = "Invalid socket type",
+ [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_UNSUP_MAJOR) ] = "Unsupported major version",
};
/*
*/
fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
- perror("socket");
+ PERROR("socket");
ret = -errno;
goto error;
}
ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
if (ret < 0) {
- perror("fcntl");
+ PERROR("fcntl");
ret = -errno;
goto error_fcntl;
}
closeret = close(fd);
if (closeret)
- perror("close");
+ PERROR("close");
}
error:
return ret;
/* Blocking call */
new_fd = accept(sock, (struct sockaddr *) &sun, &len);
if (new_fd < 0) {
- perror("accept");
+ PERROR("accept");
return -errno;
}
return new_fd;
/* Create server socket */
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- perror("socket");
+ PERROR("socket");
ret = -errno;
goto error;
}
(void) unlink(pathname);
ret = bind(fd, (struct sockaddr *) &sun, sizeof(sun));
if (ret < 0) {
- perror("bind");
+ PERROR("bind");
ret = -errno;
goto error_close;
}
closeret = close(fd);
if (closeret) {
- perror("close");
+ PERROR("close");
}
}
error:
ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
if (ret < 0) {
ret = -errno;
- perror("listen");
+ PERROR("listen");
}
return ret;
ret = close(sock);
if (ret < 0) {
- perror("close");
+ PERROR("close");
ret = -errno;
}
int shutret;
if (errno != EPIPE && errno != ECONNRESET)
- perror("recvmsg");
+ PERROR("recvmsg");
ret = -errno;
shutret = shutdown(sock, SHUT_RDWR);
if (shutret)
- fprintf(stderr, "Socket shutdown error");
+ ERR("Socket shutdown error");
}
return ret;
* Send buf data of size len. Using sendmsg API.
* Return the size of sent data.
*/
-ssize_t ustcomm_send_unix_sock(int sock, void *buf, size_t len)
+ssize_t ustcomm_send_unix_sock(int sock, const void *buf, size_t len)
{
struct msghdr msg;
struct iovec iov[1];
memset(&msg, 0, sizeof(msg));
- iov[0].iov_base = buf;
+ iov[0].iov_base = (void *) buf;
iov[0].iov_len = len;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
int shutret;
if (errno != EPIPE && errno != ECONNRESET)
- perror("sendmsg");
+ PERROR("sendmsg");
ret = -errno;
shutret = shutdown(sock, SHUT_RDWR);
if (shutret)
- fprintf(stderr, "Socket shutdown error");
+ ERR("Socket shutdown error");
}
return ret;
* We consider EPIPE and ECONNRESET as expected.
*/
if (errno != EPIPE && errno != ECONNRESET) {
- perror("sendmsg");
+ PERROR("sendmsg");
}
}
return ret;
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
if (errno != EPIPE && errno != ECONNRESET) {
- perror("recvmsg fds");
+ PERROR("recvmsg fds");
}
if (errno == EPIPE || errno == ECONNRESET)
ret = -errno;
goto end;
}
if (ret != 1) {
- fprintf(stderr, "Error: Received %zd bytes, expected %d\n",
+ ERR("Error: Received %zd bytes, expected %d\n",
ret, 1);
goto end;
}
if (msg.msg_flags & MSG_CTRUNC) {
- fprintf(stderr, "Error: Control message truncated.\n");
+ ERR("Error: Control message truncated.\n");
ret = -1;
goto end;
}
cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg) {
- fprintf(stderr, "Error: Invalid control message header\n");
+ ERR("Error: Invalid control message header\n");
ret = -1;
goto end;
}
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
- fprintf(stderr, "Didn't received any fd\n");
+ ERR("Didn't received any fd\n");
ret = -1;
goto end;
}
if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
- fprintf(stderr, "Error: Received %zu bytes of ancillary data, expected %zu\n",
+ ERR("Error: Received %zu bytes of ancillary data, expected %zu\n",
(size_t) cmsg->cmsg_len, (size_t) CMSG_LEN(sizeof_fds));
ret = -1;
goto end;
if (len < 0) {
return len;
} else {
- fprintf(stderr, "incorrect message size: %zd\n", len);
+ ERR("incorrect message size: %zd\n", len);
return -EINVAL;
}
}
return -EPIPE;
case sizeof(*lur):
if (lur->handle != expected_handle) {
- fprintf(stderr, "Unexpected result message handle: "
+ ERR("Unexpected result message handle: "
"expected: %u vs received: %u\n",
expected_handle, lur->handle);
return -EINVAL;
}
if (lur->cmd != expected_cmd) {
- fprintf(stderr, "Unexpected result message command "
+ ERR("Unexpected result message command "
"expected: %u vs received: %u\n",
expected_cmd, lur->cmd);
return -EINVAL;
len = -errno;
return len;
} else {
- fprintf(stderr, "incorrect message size: %zd\n", len);
+ ERR("incorrect message size: %zd\n", len);
return len;
}
}
error:
return ret;
}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustcomm_send_reg_msg(int sock,
+ enum ustctl_socket_type type,
+ uint32_t bits_per_long,
+ uint32_t uint8_t_alignment,
+ uint32_t uint16_t_alignment,
+ uint32_t uint32_t_alignment,
+ uint32_t uint64_t_alignment,
+ uint32_t long_alignment)
+{
+ ssize_t len;
+ struct ustctl_reg_msg reg_msg;
+
+ reg_msg.magic = LTTNG_UST_COMM_MAGIC;
+ reg_msg.major = LTTNG_UST_ABI_MAJOR_VERSION;
+ reg_msg.minor = LTTNG_UST_ABI_MINOR_VERSION;
+ reg_msg.pid = getpid();
+ reg_msg.ppid = getppid();
+ reg_msg.uid = getuid();
+ reg_msg.gid = getgid();
+ reg_msg.bits_per_long = bits_per_long;
+ reg_msg.uint8_t_alignment = uint8_t_alignment;
+ reg_msg.uint16_t_alignment = uint16_t_alignment;
+ reg_msg.uint32_t_alignment = uint32_t_alignment;
+ reg_msg.uint64_t_alignment = uint64_t_alignment;
+ reg_msg.long_alignment = long_alignment;
+ reg_msg.socket_type = type;
+ lttng_ust_getprocname(reg_msg.name);
+ memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
+
+ len = ustcomm_send_unix_sock(sock, ®_msg, sizeof(reg_msg));
+ if (len > 0 && len != sizeof(reg_msg))
+ return -EIO;
+ if (len < 0)
+ return len;
+ return 0;
+}
+
+static
+int serialize_basic_type(enum lttng_abstract_types atype,
+ union _ustctl_basic_type *ubt,
+ const union _lttng_basic_type *lbt)
+{
+ switch (atype) {
+ case atype_integer:
+ {
+ struct ustctl_integer_type *uit;
+ const struct lttng_integer_type *lit;
+
+ uit = &ubt->integer;
+ lit = &lbt->integer;
+ uit->size = lit->size;
+ uit->signedness = lit->signedness;
+ uit->reverse_byte_order = lit->reverse_byte_order;
+ uit->base = lit->base;
+ uit->encoding = lit->encoding;
+ uit->alignment = lit->alignment;
+ break;
+ }
+ case atype_string:
+ {
+ ubt->string.encoding = lbt->string.encoding;
+ break;
+ }
+ case atype_float:
+ {
+ struct ustctl_float_type *uft;
+ const struct lttng_float_type *lft;
+
+ uft = &ubt->_float;
+ lft = &lbt->_float;
+ uft->exp_dig = lft->exp_dig;
+ uft->mant_dig = lft->mant_dig;
+ uft->alignment = lft->alignment;
+ uft->reverse_byte_order = lft->reverse_byte_order;
+ break;
+ }
+ case atype_enum:
+ case atype_array:
+ case atype_sequence:
+ default:
+ return -EINVAL;
+ }
+ return 0;
+
+}
+
+static
+int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
+{
+ int ret;
+
+ switch (lt->atype) {
+ case atype_integer:
+ case atype_float:
+ case atype_string:
+ ret = serialize_basic_type(lt->atype,
+ &ut->u.basic, <->u.basic);
+ if (ret)
+ return ret;
+ break;
+ case atype_array:
+ {
+ struct ustctl_basic_type *ubt;
+ const struct lttng_basic_type *lbt;
+ int ret;
+
+ ubt = &ut->u.array.elem_type;
+ lbt = <->u.array.elem_type;
+ ut->u.array.length = lt->u.array.length;
+ ret = serialize_basic_type(lbt->atype,
+ &ubt->u.basic, &lbt->u.basic);
+ if (ret)
+ return -EINVAL;
+ break;
+ }
+ case atype_sequence:
+ {
+ struct ustctl_basic_type *ubt;
+ const struct lttng_basic_type *lbt;
+ int ret;
+
+ ubt = &ut->u.sequence.length_type;
+ lbt = <->u.sequence.length_type;
+ ret = serialize_basic_type(lbt->atype,
+ &ubt->u.basic, &lbt->u.basic);
+ if (ret)
+ return -EINVAL;
+ ubt = &ut->u.sequence.elem_type;
+ lbt = <->u.sequence.elem_type;
+ ret = serialize_basic_type(lbt->atype,
+ &ubt->u.basic, &lbt->u.basic);
+ if (ret)
+ return -EINVAL;
+ break;
+ }
+ case atype_enum:
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static
+int serialize_fields(size_t *_nr_write_fields,
+ struct ustctl_field **ustctl_fields,
+ size_t nr_fields,
+ const struct lttng_event_field *lttng_fields)
+{
+ struct ustctl_field *fields;
+ int i, ret;
+ size_t nr_write_fields = 0;
+
+ fields = zmalloc(nr_fields * sizeof(*fields));
+ if (!fields)
+ return -ENOMEM;
+
+ for (i = 0; i < nr_fields; i++) {
+ struct ustctl_field *f;
+ const struct lttng_event_field *lf;
+
+ f = &fields[nr_write_fields];
+ lf = <tng_fields[i];
+
+ /* skip 'nowrite' fields */
+ if (lf->nowrite)
+ continue;
+ strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+ f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ ret = serialize_one_type(&f->type, &lf->type);
+ if (ret)
+ goto error_type;
+ nr_write_fields++;
+ }
+
+ *_nr_write_fields = nr_write_fields;
+ *ustctl_fields = fields;
+ return 0;
+
+error_type:
+ free(fields);
+ return ret;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustcomm_register_event(int sock,
+ int session_objd, /* session descriptor */
+ int channel_objd, /* channel descriptor */
+ const char *event_name, /* event name (input) */
+ int loglevel,
+ const char *signature, /* event signature (input) */
+ size_t nr_fields, /* fields */
+ const struct lttng_event_field *lttng_fields,
+ const char *model_emf_uri,
+ uint32_t *id) /* event id (output) */
+{
+ ssize_t len;
+ struct {
+ struct ustcomm_notify_hdr header;
+ struct ustcomm_notify_event_msg m;
+ } msg;
+ struct {
+ struct ustcomm_notify_hdr header;
+ struct ustcomm_notify_event_reply r;
+ } reply;
+ size_t signature_len, fields_len, model_emf_uri_len;
+ struct ustctl_field *fields;
+ size_t nr_write_fields = 0;
+ int ret;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.header.notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
+ msg.m.session_objd = session_objd;
+ msg.m.channel_objd = channel_objd;
+ strncpy(msg.m.event_name, event_name, LTTNG_UST_SYM_NAME_LEN);
+ msg.m.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ msg.m.loglevel = loglevel;
+ signature_len = strlen(signature) + 1;
+ msg.m.signature_len = signature_len;
+
+ /* Calculate fields len, serialize fields. */
+ if (nr_fields > 0) {
+ ret = serialize_fields(&nr_write_fields, &fields,
+ nr_fields, lttng_fields);
+ if (ret)
+ return ret;
+ }
+
+ fields_len = sizeof(*fields) * nr_write_fields;
+ msg.m.fields_len = fields_len;
+ if (model_emf_uri) {
+ model_emf_uri_len = strlen(model_emf_uri) + 1;
+ } else {
+ model_emf_uri_len = 0;
+ }
+ msg.m.model_emf_uri_len = model_emf_uri_len;
+ len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
+ if (len > 0 && len != sizeof(msg)) {
+ free(fields);
+ return -EIO;
+ }
+ if (len < 0) {
+ free(fields);
+ return len;
+ }
+
+ /* send signature */
+ len = ustcomm_send_unix_sock(sock, signature, signature_len);
+ if (len > 0 && len != signature_len) {
+ free(fields);
+ return -EIO;
+ }
+ if (len < 0) {
+ free(fields);
+ return len;
+ }
+
+ /* send fields */
+ if (fields_len > 0) {
+ len = ustcomm_send_unix_sock(sock, fields, fields_len);
+ free(fields);
+ if (len > 0 && len != fields_len) {
+ return -EIO;
+ }
+ if (len < 0) {
+ return len;
+ }
+ }
+
+ if (model_emf_uri_len) {
+ /* send model_emf_uri */
+ len = ustcomm_send_unix_sock(sock, model_emf_uri,
+ model_emf_uri_len);
+ if (len > 0 && len != model_emf_uri_len)
+ return -EIO;
+ if (len < 0)
+ return len;
+ }
+
+ /* receive reply */
+ len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
+ switch (len) {
+ case 0: /* orderly shutdown */
+ return -EPIPE;
+ case sizeof(reply):
+ if (reply.header.notify_cmd != msg.header.notify_cmd) {
+ ERR("Unexpected result message command "
+ "expected: %u vs received: %u\n",
+ msg.header.notify_cmd, reply.header.notify_cmd);
+ return -EINVAL;
+ }
+ if (reply.r.ret_code > 0)
+ return -EINVAL;
+ if (reply.r.ret_code < 0)
+ return reply.r.ret_code;
+ *id = reply.r.event_id;
+ DBG("Sent register event notification for name \"%s\": ret_code %d, event_id %u\n",
+ event_name, reply.r.ret_code, reply.r.event_id);
+ return 0;
+ default:
+ if (len < 0) {
+ /* Transport level error */
+ if (errno == EPIPE || errno == ECONNRESET)
+ len = -errno;
+ return len;
+ } else {
+ ERR("incorrect message size: %zd\n", len);
+ return len;
+ }
+ }
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_channel(int sock,
+ int session_objd, /* session descriptor */
+ int channel_objd, /* channel descriptor */
+ size_t nr_ctx_fields,
+ const struct lttng_event_field *ctx_fields,
+ uint32_t *chan_id, /* channel id (output) */
+ int *header_type) /* header type (output) */
+{
+ ssize_t len;
+ struct {
+ struct ustcomm_notify_hdr header;
+ struct ustcomm_notify_channel_msg m;
+ } msg;
+ struct {
+ struct ustcomm_notify_hdr header;
+ struct ustcomm_notify_channel_reply r;
+ } reply;
+ size_t fields_len;
+ struct ustctl_field *fields;
+ int ret;
+ size_t nr_write_fields = 0;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.header.notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
+ msg.m.session_objd = session_objd;
+ msg.m.channel_objd = channel_objd;
+
+ /* Calculate fields len, serialize fields. */
+ if (nr_ctx_fields > 0) {
+ ret = serialize_fields(&nr_write_fields, &fields,
+ nr_ctx_fields, ctx_fields);
+ if (ret)
+ return ret;
+ }
+
+ fields_len = sizeof(*fields) * nr_write_fields;
+ msg.m.ctx_fields_len = fields_len;
+ len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
+ if (len > 0 && len != sizeof(msg)) {
+ free(fields);
+ return -EIO;
+ }
+ if (len < 0) {
+ free(fields);
+ return len;
+ }
+
+ /* send fields */
+ if (fields_len > 0) {
+ len = ustcomm_send_unix_sock(sock, fields, fields_len);
+ free(fields);
+ if (len > 0 && len != fields_len) {
+ return -EIO;
+ }
+ if (len < 0) {
+ return len;
+ }
+ }
+
+ len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
+ switch (len) {
+ case 0: /* orderly shutdown */
+ return -EPIPE;
+ case sizeof(reply):
+ if (reply.header.notify_cmd != msg.header.notify_cmd) {
+ ERR("Unexpected result message command "
+ "expected: %u vs received: %u\n",
+ msg.header.notify_cmd, reply.header.notify_cmd);
+ return -EINVAL;
+ }
+ if (reply.r.ret_code > 0)
+ return -EINVAL;
+ if (reply.r.ret_code < 0)
+ return reply.r.ret_code;
+ *chan_id = reply.r.chan_id;
+ switch (reply.r.header_type) {
+ case 1:
+ case 2:
+ *header_type = reply.r.header_type;
+ break;
+ default:
+ ERR("Unexpected channel header type %u\n",
+ reply.r.header_type);
+ return -EINVAL;
+ }
+ DBG("Sent register channel notification: chan_id %d, header_type %d\n",
+ reply.r.chan_id, reply.r.header_type);
+ return 0;
+ default:
+ if (len < 0) {
+ /* Transport level error */
+ if (errno == EPIPE || errno == ECONNRESET)
+ len = -errno;
+ return len;
+ } else {
+ ERR("incorrect message size: %zd\n", len);
+ return len;
+ }
+ }
+}
#include <lttng/ust-abi.h>
#include <lttng/ust-events.h>
#include <sys/mman.h>
+#include <byteswap.h>
#include <usterr-signal-safe.h>
#include <ust-comm.h>
}
}
break;
+ case LTTNG_UST_OBJECT_TYPE_EVENT:
+ case LTTNG_UST_OBJECT_TYPE_CONTEXT:
+ break;
default:
assert(0);
}
event_data = zmalloc(sizeof(*event_data));
if (!event_data)
return -ENOMEM;
+ event_data->type = LTTNG_UST_OBJECT_TYPE_EVENT;
memset(&lum, 0, sizeof(lum));
lum.handle = channel_data->handle;
lum.cmd = LTTNG_UST_EVENT;
context_data = zmalloc(sizeof(*context_data));
if (!context_data)
return -ENOMEM;
+ context_data->type = LTTNG_UST_OBJECT_TYPE_CONTEXT;
memset(&lum, 0, sizeof(lum));
lum.handle = obj_data->handle;
lum.cmd = LTTNG_UST_CONTEXT;
free(context_data);
return ret;
}
- context_data->handle = lur.ret_val;
- DBG("received context handle %u", context_data->handle);
+ context_data->handle = -1;
+ DBG("Context created successfully");
*_context_data = context_data;
return ret;
}
transport = lttng_transport_find(transport_name);
if (!transport) {
DBG("LTTng transport %s not found\n",
- transport_name);
+ transport_name);
return NULL;
}
return NULL;
chan->chan = transport->ops.channel_create(transport_name, NULL,
- attr->subbuf_size, attr->num_subbuf,
+ attr->subbuf_size, attr->num_subbuf,
attr->switch_timer_interval,
- attr->read_timer_interval,
+ attr->read_timer_interval,
attr->uuid);
if (!chan->chan) {
goto chan_error;
if (chan->backend.config.output != RING_BUFFER_MMAP)
return -EINVAL;
sb_bindex = subbuffer_id_get_index(&chan->backend.config,
- buf->backend.buf_rsb.id);
+ buf->backend.buf_rsb.id);
*off = shmp(consumer_chan->chan->handle,
shmp_index(consumer_chan->chan->handle, buf->backend.array, sb_bindex)->shmp)->mmap_offset;
return 0;
consumer_chan->chan->handle);
}
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_recv_reg_msg(int sock,
+ enum ustctl_socket_type *type,
+ uint32_t *major,
+ uint32_t *minor,
+ uint32_t *pid,
+ uint32_t *ppid,
+ uint32_t *uid,
+ uint32_t *gid,
+ uint32_t *bits_per_long,
+ uint32_t *uint8_t_alignment,
+ uint32_t *uint16_t_alignment,
+ uint32_t *uint32_t_alignment,
+ uint32_t *uint64_t_alignment,
+ uint32_t *long_alignment,
+ int *byte_order,
+ char *name)
+{
+ ssize_t len;
+ struct ustctl_reg_msg reg_msg;
+
+ len = ustcomm_recv_unix_sock(sock, ®_msg, sizeof(reg_msg));
+ if (len > 0 && len != sizeof(reg_msg))
+ return -EIO;
+ if (len == 0)
+ return -EPIPE;
+ if (len < 0)
+ return len;
+
+ if (reg_msg.magic == LTTNG_UST_COMM_MAGIC) {
+ *byte_order = BYTE_ORDER == BIG_ENDIAN ?
+ BIG_ENDIAN : LITTLE_ENDIAN;
+ } else if (reg_msg.magic == bswap_32(LTTNG_UST_COMM_MAGIC)) {
+ *byte_order = BYTE_ORDER == BIG_ENDIAN ?
+ LITTLE_ENDIAN : BIG_ENDIAN;
+ } else {
+ return -LTTNG_UST_ERR_INVAL_MAGIC;
+ }
+ switch (reg_msg.socket_type) {
+ case 0: *type = USTCTL_SOCKET_CMD;
+ break;
+ case 1: *type = USTCTL_SOCKET_NOTIFY;
+ break;
+ default:
+ return -LTTNG_UST_ERR_INVAL_SOCKET_TYPE;
+ }
+ *major = reg_msg.major;
+ *minor = reg_msg.minor;
+ *pid = reg_msg.pid;
+ *ppid = reg_msg.ppid;
+ *uid = reg_msg.uid;
+ *gid = reg_msg.gid;
+ *bits_per_long = reg_msg.bits_per_long;
+ *uint8_t_alignment = reg_msg.uint8_t_alignment;
+ *uint16_t_alignment = reg_msg.uint16_t_alignment;
+ *uint32_t_alignment = reg_msg.uint32_t_alignment;
+ *uint64_t_alignment = reg_msg.uint64_t_alignment;
+ *long_alignment = reg_msg.long_alignment;
+ memcpy(name, reg_msg.name, LTTNG_UST_ABI_PROCNAME_LEN);
+ if (reg_msg.major != LTTNG_UST_ABI_MAJOR_VERSION) {
+ return -LTTNG_UST_ERR_UNSUP_MAJOR;
+ }
+
+ return 0;
+}
+
+int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd)
+{
+ struct ustcomm_notify_hdr header;
+ ssize_t len;
+
+ len = ustcomm_recv_unix_sock(sock, &header, sizeof(header));
+ if (len > 0 && len != sizeof(header))
+ return -EIO;
+ if (len == 0)
+ return -EPIPE;
+ if (len < 0)
+ return len;
+ switch (header.notify_cmd) {
+ case 0:
+ *notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
+ break;
+ case 1:
+ *notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_recv_register_event(int sock,
+ int *session_objd,
+ int *channel_objd,
+ char *event_name,
+ int *loglevel,
+ char **signature,
+ size_t *nr_fields,
+ struct ustctl_field **fields,
+ char **model_emf_uri)
+{
+ ssize_t len;
+ struct ustcomm_notify_event_msg msg;
+ size_t signature_len, fields_len, model_emf_uri_len;
+ char *a_sign = NULL, *a_model_emf_uri = NULL;
+ struct ustctl_field *a_fields = NULL;
+
+ len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
+ if (len > 0 && len != sizeof(msg))
+ return -EIO;
+ if (len == 0)
+ return -EPIPE;
+ if (len < 0)
+ return len;
+
+ *session_objd = msg.session_objd;
+ *channel_objd = msg.channel_objd;
+ strncpy(event_name, msg.event_name, LTTNG_UST_SYM_NAME_LEN);
+ event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ *loglevel = msg.loglevel;
+ signature_len = msg.signature_len;
+ fields_len = msg.fields_len;
+
+ if (fields_len % sizeof(*a_fields) != 0) {
+ return -EINVAL;
+ }
+
+ model_emf_uri_len = msg.model_emf_uri_len;
+
+ /* recv signature. contains at least \0. */
+ a_sign = zmalloc(signature_len);
+ if (!a_sign)
+ return -ENOMEM;
+ len = ustcomm_recv_unix_sock(sock, a_sign, signature_len);
+ if (len > 0 && len != signature_len) {
+ len = -EIO;
+ goto signature_error;
+ }
+ if (len == 0) {
+ len = -EPIPE;
+ goto signature_error;
+ }
+ if (len < 0) {
+ goto signature_error;
+ }
+ /* Enforce end of string */
+ signature[signature_len - 1] = '\0';
+
+ /* recv fields */
+ if (fields_len) {
+ a_fields = zmalloc(fields_len);
+ if (!a_fields) {
+ len = -ENOMEM;
+ goto signature_error;
+ }
+ len = ustcomm_recv_unix_sock(sock, a_fields, fields_len);
+ if (len > 0 && len != fields_len) {
+ len = -EIO;
+ goto fields_error;
+ }
+ if (len == 0) {
+ len = -EPIPE;
+ goto fields_error;
+ }
+ if (len < 0) {
+ goto fields_error;
+ }
+ }
+
+ if (model_emf_uri_len) {
+ /* recv model_emf_uri_len */
+ a_model_emf_uri = zmalloc(model_emf_uri_len);
+ if (!a_model_emf_uri) {
+ len = -ENOMEM;
+ goto fields_error;
+ }
+ len = ustcomm_recv_unix_sock(sock, a_model_emf_uri,
+ model_emf_uri_len);
+ if (len > 0 && len != model_emf_uri_len) {
+ len = -EIO;
+ goto model_error;
+ }
+ if (len == 0) {
+ len = -EPIPE;
+ goto model_error;
+ }
+ if (len < 0) {
+ goto model_error;
+ }
+ /* Enforce end of string */
+ a_model_emf_uri[model_emf_uri_len - 1] = '\0';
+ }
+
+ *signature = a_sign;
+ *nr_fields = fields_len / sizeof(*a_fields);
+ *fields = a_fields;
+ *model_emf_uri = a_model_emf_uri;
+
+ return 0;
+
+model_error:
+ free(a_model_emf_uri);
+fields_error:
+ free(a_fields);
+signature_error:
+ free(a_sign);
+ return len;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_register_event(int sock,
+ uint32_t id,
+ int ret_code)
+{
+ ssize_t len;
+ struct {
+ struct ustcomm_notify_hdr header;
+ struct ustcomm_notify_event_reply r;
+ } reply;
+
+ memset(&reply, 0, sizeof(reply));
+ reply.header.notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
+ reply.r.ret_code = ret_code;
+ reply.r.event_id = id;
+ len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
+ if (len > 0 && len != sizeof(reply))
+ return -EIO;
+ if (len < 0)
+ return len;
+ return 0;
+}
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int ustctl_recv_register_channel(int sock,
+ int *session_objd, /* session descriptor (output) */
+ int *channel_objd, /* channel descriptor (output) */
+ size_t *nr_fields,
+ struct ustctl_field **fields)
+{
+ ssize_t len;
+ struct ustcomm_notify_channel_msg msg;
+ size_t fields_len;
+ struct ustctl_field *a_fields;
+
+ len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
+ if (len > 0 && len != sizeof(msg))
+ return -EIO;
+ if (len == 0)
+ return -EPIPE;
+ if (len < 0)
+ return len;
+
+ *session_objd = msg.session_objd;
+ *channel_objd = msg.channel_objd;
+ fields_len = msg.ctx_fields_len;
+
+ if (fields_len % sizeof(*a_fields) != 0) {
+ return -EINVAL;
+ }
+
+ /* recv fields */
+ if (fields_len) {
+ a_fields = zmalloc(fields_len);
+ if (!a_fields) {
+ len = -ENOMEM;
+ goto alloc_error;
+ }
+ len = ustcomm_recv_unix_sock(sock, a_fields, fields_len);
+ if (len > 0 && len != fields_len) {
+ len = -EIO;
+ goto fields_error;
+ }
+ if (len == 0) {
+ len = -EPIPE;
+ goto fields_error;
+ }
+ if (len < 0) {
+ goto fields_error;
+ }
+ *fields = a_fields;
+ } else {
+ *fields = NULL;
+ }
+ *nr_fields = fields_len / sizeof(*a_fields);
+ return 0;
+
+fields_error:
+ free(a_fields);
+alloc_error:
+ return len;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_register_channel(int sock,
+ uint32_t chan_id,
+ enum ustctl_channel_header header_type,
+ int ret_code)
+{
+ ssize_t len;
+ struct {
+ struct ustcomm_notify_hdr header;
+ struct ustcomm_notify_channel_reply r;
+ } reply;
+
+ memset(&reply, 0, sizeof(reply));
+ reply.header.notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
+ reply.r.ret_code = ret_code;
+ reply.r.chan_id = chan_id;
+ switch (header_type) {
+ case USTCTL_CHANNEL_HEADER_COMPACT:
+ reply.r.header_type = 1;
+ break;
+ case USTCTL_CHANNEL_HEADER_LARGE:
+ reply.r.header_type = 2;
+ break;
+ default:
+ reply.r.header_type = 0;
+ break;
+ }
+ len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
+ if (len > 0 && len != sizeof(reply))
+ return -EIO;
+ if (len < 0)
+ return len;
+ return 0;
+}
+
static __attribute__((constructor))
void ustctl_init(void)
{
#include <usterr-signal-safe.h>
#include <helper.h>
+#include <ust-ctl.h>
+#include <ust-comm.h>
#include "error.h"
#include "compat.h"
#include "lttng-ust-uuid.h"
{
int ret = 0;
struct lttng_channel *chan;
+ int notify_socket;
if (session->active) {
ret = -EBUSY;
goto end;
}
+ notify_socket = lttng_get_notify_socket(session->owner);
+ if (notify_socket < 0)
+ return notify_socket;
+
/* We need to sync enablers with session before activation. */
lttng_session_sync_enablers(session);
* we need to use.
*/
cds_list_for_each_entry(chan, &session->chan_head, node) {
+ const struct lttng_ctx *ctx;
+ const struct lttng_event_field *fields = NULL;
+ size_t nr_fields = 0;
+
+ /* don't change it if session stop/restart */
if (chan->header_type)
- continue; /* don't change it if session stop/restart */
- if (chan->free_event_id < 31)
- chan->header_type = 1; /* compact */
- else
- chan->header_type = 2; /* large */
+ continue;
+ ctx = chan->ctx;
+ if (ctx) {
+ nr_fields = ctx->nr_fields;
+ fields = &ctx->fields->event_field;
+ }
+ ret = ustcomm_register_channel(notify_socket,
+ session->objd,
+ chan->objd,
+ nr_fields,
+ fields,
+ &chan->id,
+ &chan->header_type);
+ if (ret)
+ return ret;
}
CMM_ACCESS_ONCE(session->active) = 1;
{
const char *event_name = desc->name;
struct lttng_event *event;
+ struct lttng_session *session = chan->session;
struct cds_hlist_head *head;
struct cds_hlist_node *node;
int ret = 0;
size_t name_len = strlen(event_name);
uint32_t hash;
+ int notify_socket, loglevel;
+ const char *uri;
- if (chan->used_event_id == -1U) {
- ret = -ENOMEM;
- goto full;
- }
hash = jhash(event_name, name_len, 0);
head = &chan->session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)];
cds_hlist_for_each_entry(event, node, head, hlist) {
}
}
+ notify_socket = lttng_get_notify_socket(session->owner);
+ if (notify_socket < 0) {
+ ret = notify_socket;
+ goto socket_error;
+ }
+
/*
* Check if loglevel match. Refuse to connect event if not.
*/
}
event->chan = chan;
- /*
- * used_event_id counts the maximum number of event IDs that can
- * register if all probes register.
- */
- chan->used_event_id++;
event->enabled = 1;
CDS_INIT_LIST_HEAD(&event->bytecode_runtime_head);
CDS_INIT_LIST_HEAD(&event->enablers_ref_head);
event->desc = desc;
+
+ if (desc->loglevel)
+ loglevel = *(*event->desc->loglevel);
+ else
+ loglevel = TRACE_DEFAULT;
+ if (desc->u.ext.model_emf_uri)
+ uri = *(desc->u.ext.model_emf_uri);
+ else
+ uri = NULL;
+
+ /* Fetch event ID from sessiond */
+ ret = ustcomm_register_event(notify_socket,
+ session->objd,
+ chan->objd,
+ event_name,
+ loglevel,
+ desc->signature,
+ desc->nr_fields,
+ desc->fields,
+ uri,
+ &event->id);
+ if (ret < 0) {
+ goto sessiond_register_error;
+ }
/* Populate lttng_event structure before tracepoint registration. */
cmm_smp_wmb();
ret = __tracepoint_probe_register(event_name,
desc->probe_callback,
event, desc->signature);
if (ret)
- goto register_error;
- event->id = chan->free_event_id++;
+ goto tracepoint_register_error;
+
ret = _lttng_event_metadata_statedump(chan->session, chan, event);
if (ret)
goto statedump_error;
WARN_ON_ONCE(__tracepoint_probe_unregister(event_name,
desc->probe_callback,
event));
-register_error:
+tracepoint_register_error:
+sessiond_register_error:
free(event);
cache_error:
+socket_error:
exist:
-full:
return ret;
}
ret = lttng_event_create(probe_desc->event_desc[i],
enabler->chan);
if (ret) {
- DBG("Unable to create event %s\n",
- probe_desc->event_desc[i]->name);
+ DBG("Unable to create event %s, error %d\n",
+ probe_desc->event_desc[i]->name, ret);
}
}
}
const char *lttng_ust_obj_get_name(int id);
+int lttng_get_notify_socket(void *owner);
+
#endif /* _LTTNG_TRACER_CORE_H */
goto objd_error;
}
session->objd = session_objd;
+ session->owner = owner;
return session_objd;
objd_error:
long lttng_abi_tracer_version(int objd,
struct lttng_ust_tracer_version *v)
{
- v->major = LTTNG_UST_INTERNAL_MAJOR_VERSION;
- v->minor = LTTNG_UST_INTERNAL_MINOR_VERSION;
- v->patchlevel = LTTNG_UST_INTERNAL_PATCHLEVEL_VERSION;
+ v->major = LTTNG_UST_MAJOR_VERSION;
+ v->minor = LTTNG_UST_MINOR_VERSION;
+ v->patchlevel = LTTNG_UST_PATCHLEVEL_VERSION;
return 0;
}
lttng_chan->enabled = 1;
lttng_chan->ctx = NULL;
lttng_chan->session = session;
- lttng_chan->free_event_id = 0;
- lttng_chan->used_event_id = 0;
lttng_chan->ops = &transport->ops;
memcpy(<tng_chan->chan->backend.config,
transport->client_config,
lttng_chan->header_type = 0;
lttng_chan->handle = channel_handle;
lttng_chan->metadata_dumped = 0;
- lttng_chan->id = session->free_chan_id++;
lttng_chan->type = type;
/*
char sock_path[PATH_MAX];
int socket;
+ int notify_socket;
char wait_shm_path[PATH_MAX];
char *wait_shm_mmap;
.allowed = 1,
.thread_active = 0,
- .sock_path = DEFAULT_GLOBAL_APPS_UNIX_SOCK,
+ .sock_path = LTTNG_DEFAULT_RUNDIR "/" LTTNG_UST_SOCK_FILENAME,
.socket = -1,
+ .notify_socket = -1,
- .wait_shm_path = DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
+ .wait_shm_path = "/" LTTNG_UST_WAIT_FILENAME,
};
/* TODO: allow global_apps_sock_path override */
.thread_active = 0,
.socket = -1,
+ .notify_socket = -1,
};
static int wait_poll_fallback;
asm volatile ("" : : "m" (URCU_TLS(lttng_ust_nest_count)));
}
+int lttng_get_notify_socket(void *owner)
+{
+ struct sock_info *info = owner;
+
+ return info->notify_socket;
+}
+
static
void print_cmd(int cmd, int handle)
{
return -ENOENT;
}
local_apps.allowed = 1;
- snprintf(local_apps.sock_path, PATH_MAX,
- DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
- snprintf(local_apps.wait_shm_path, PATH_MAX,
- DEFAULT_HOME_APPS_WAIT_SHM_PATH, uid);
+ snprintf(local_apps.sock_path, PATH_MAX, "%s/%s/%s",
+ home_dir,
+ LTTNG_DEFAULT_HOME_RUNDIR,
+ LTTNG_UST_SOCK_FILENAME);
+ snprintf(local_apps.wait_shm_path, PATH_MAX, "/%s-%u",
+ LTTNG_UST_WAIT_FILENAME,
+ uid);
return 0;
}
static
-int register_app_to_sessiond(int socket)
+int register_to_sessiond(int socket, enum ustctl_socket_type type)
{
- ssize_t ret;
- struct {
- uint32_t major;
- uint32_t minor;
- pid_t pid;
- pid_t ppid;
- uid_t uid;
- gid_t gid;
- uint32_t bits_per_long;
- char name[16]; /* process name */
- } reg_msg;
-
- reg_msg.major = LTTNG_UST_COMM_VERSION_MAJOR;
- reg_msg.minor = LTTNG_UST_COMM_VERSION_MINOR;
- reg_msg.pid = getpid();
- reg_msg.ppid = getppid();
- reg_msg.uid = getuid();
- reg_msg.gid = getgid();
- reg_msg.bits_per_long = CAA_BITS_PER_LONG;
- lttng_ust_getprocname(reg_msg.name);
-
- ret = ustcomm_send_unix_sock(socket, ®_msg, sizeof(reg_msg));
- if (ret >= 0 && ret != sizeof(reg_msg))
- return -EIO;
- return ret;
+ return ustcomm_send_reg_msg(socket,
+ type,
+ CAA_BITS_PER_LONG,
+ lttng_alignof(uint8_t) * CHAR_BIT,
+ lttng_alignof(uint16_t) * CHAR_BIT,
+ lttng_alignof(uint32_t) * CHAR_BIT,
+ lttng_alignof(uint64_t) * CHAR_BIT,
+ lttng_alignof(unsigned long) * CHAR_BIT);
}
static
if (sock_info->socket != -1) {
ret = ustcomm_close_unix_sock(sock_info->socket);
if (ret) {
- ERR("Error closing apps socket");
+ ERR("Error closing ust cmd socket");
}
sock_info->socket = -1;
}
+ if (sock_info->notify_socket != -1) {
+ ret = ustcomm_close_unix_sock(sock_info->notify_socket);
+ if (ret) {
+ ERR("Error closing ust notify socket");
+ }
+ sock_info->notify_socket = -1;
+ }
if (sock_info->root_handle != -1) {
ret = lttng_ust_objd_unref(sock_info->root_handle);
if (ret) {
{
struct sock_info *sock_info = arg;
int sock, ret, prev_connect_failed = 0, has_waited = 0;
+ int open_sock[2];
+ int i;
/* Restart trying to connect to the session daemon */
restart:
if (sock_info->socket != -1) {
ret = ustcomm_close_unix_sock(sock_info->socket);
if (ret) {
- ERR("Error closing %s apps socket", sock_info->name);
+ ERR("Error closing %s ust cmd socket",
+ sock_info->name);
}
sock_info->socket = -1;
}
+ if (sock_info->notify_socket != -1) {
+ ret = ustcomm_close_unix_sock(sock_info->notify_socket);
+ if (ret) {
+ ERR("Error closing %s ust notify socket",
+ sock_info->name);
+ }
+ sock_info->notify_socket = -1;
+ }
/* Register */
- ret = ustcomm_connect_unix_sock(sock_info->sock_path);
- if (ret < 0) {
- DBG("Info: sessiond not accepting connections to %s apps socket", sock_info->name);
- prev_connect_failed = 1;
- /*
- * If we cannot find the sessiond daemon, don't delay
- * constructor execution.
- */
- ret = handle_register_done(sock_info);
- assert(!ret);
- ust_unlock();
- goto restart;
+ for (i = 0; i < 2; i++) {
+ ret = ustcomm_connect_unix_sock(sock_info->sock_path);
+ if (ret < 0) {
+ DBG("Info: sessiond not accepting connections to %s apps socket", sock_info->name);
+ prev_connect_failed = 1;
+ /*
+ * If we cannot find the sessiond daemon, don't delay
+ * constructor execution.
+ */
+ ret = handle_register_done(sock_info);
+ assert(!ret);
+ ust_unlock();
+ goto restart;
+ }
+ open_sock[i] = ret;
}
- sock_info->socket = sock = ret;
+ sock_info->socket = open_sock[0];
+ sock_info->notify_socket = open_sock[1];
/*
* Create only one root handle per listener thread for the whole
sock_info->root_handle = ret;
}
- ret = register_app_to_sessiond(sock);
+ ret = register_to_sessiond(sock_info->socket, USTCTL_SOCKET_CMD);
if (ret < 0) {
- ERR("Error registering to %s apps socket", sock_info->name);
+ ERR("Error registering to %s ust cmd socket",
+ sock_info->name);
prev_connect_failed = 1;
/*
* If we cannot register to the sessiond daemon, don't
ust_unlock();
goto restart;
}
+ ret = register_to_sessiond(sock_info->notify_socket,
+ USTCTL_SOCKET_NOTIFY);
+ if (ret < 0) {
+ ERR("Error registering to %s ust notify socket",
+ sock_info->name);
+ prev_connect_failed = 1;
+ /*
+ * If we cannot register to the sessiond daemon, don't
+ * delay constructor execution.
+ */
+ ret = handle_register_done(sock_info);
+ assert(!ret);
+ ust_unlock();
+ goto restart;
+ }
+ sock = sock_info->socket;
+
ust_unlock();
for (;;) {