/* * Ask the session daemon for all available events of a session channel. * Sets the contents of the events array. * Returns the number of lttng_event entries in events; * on error, returns a negative value. */ int lttng_list_events(struct lttng_handle *handle, const char *channel_name, struct lttng_event **events) { int ret; struct lttcomm_session_msg lsm; /* Safety check. An handle and channel name are mandatory */ if (handle == NULL || channel_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_LIST_EVENTS; lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); lttng_ctl_copy_string(lsm.u.list.channel_name, channel_name, sizeof(lsm.u.list.channel_name)); lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); ret = lttng_ctl_ask_sessiond(&lsm, (void**) events); if (ret < 0) { return ret; } return ret / sizeof(struct lttng_event); }
/* * Add context to a channel. * * If the given channel is NULL, add the contexts to all channels. * The event_name param is ignored. * * Returns the size of the returned payload data or a negative error code. */ int lttng_add_context(struct lttng_handle *handle, struct lttng_event_context *ctx, const char *event_name, const char *channel_name) { struct lttcomm_session_msg lsm; /* Safety check. Both are mandatory */ if (handle == NULL || ctx == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_ADD_CONTEXT; /* If no channel name, send empty string. */ if (channel_name == NULL) { lttng_ctl_copy_string(lsm.u.context.channel_name, "", sizeof(lsm.u.context.channel_name)); } else { lttng_ctl_copy_string(lsm.u.context.channel_name, channel_name, sizeof(lsm.u.context.channel_name)); } lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context)); lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Enable channel per domain * Returns size of returned session payload data or a negative error code. */ int lttng_enable_channel(struct lttng_handle *handle, struct lttng_channel *chan) { struct lttcomm_session_msg lsm; /* * NULL arguments are forbidden. No default values. */ if (handle == NULL || chan == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); memcpy(&lsm.u.channel.chan, chan, sizeof(lsm.u.channel.chan)); lsm.cmd_type = LTTNG_ENABLE_CHANNEL; lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Set URL for a consumer for a session and domain. * * Return 0 on success, else a negative value. */ int lttng_set_consumer_url(struct lttng_handle *handle, const char *control_url, const char *data_url) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (handle == NULL || (control_url == NULL && data_url == NULL)) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_SET_CONSUMER_URI; lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); size = uri_parse_str_urls(control_url, data_url, &uris); if (size < 0) { return -LTTNG_ERR_INVALID; } lsm.u.uri.size = size; ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); free(uris); return ret; }
/* * For a given session name, this call checks if the data is ready to be read * or is still being extracted by the consumer(s) hence not ready to be used by * any readers. */ int lttng_data_pending(const char *session_name) { int ret; struct lttcomm_session_msg lsm; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_DATA_PENDING; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); ret = lttng_ctl_ask_sessiond(&lsm, NULL); /* * The lttng_ctl_ask_sessiond function negate the return code if it's not * LTTNG_OK so getting -1 means that the reply ret_code was 1 thus meaning * that the data is available. Yes it is hackish but for now this is the * only way. */ if (ret == -1) { ret = 1; } return ret; }
/* * List PIDs in the tracker. * * @enabled is set to whether the PID tracker is enabled. * @pids is set to an allocated array of PIDs currently tracked. On * success, @pids must be freed by the caller. * @nr_pids is set to the number of entries contained by the @pids array. * * Returns 0 on success, else a negative LTTng error code. */ int lttng_list_tracker_pids(struct lttng_handle *handle, int *_enabled, int32_t **_pids, size_t *_nr_pids) { int ret, enabled = 1; struct lttcomm_session_msg lsm; size_t nr_pids; int32_t *pids; if (handle == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_LIST_TRACKER_PIDS; lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pids); if (ret < 0) { return ret; } nr_pids = ret / sizeof(int32_t); if (nr_pids == 1 && pids[0] == -1) { free(pids); pids = NULL; enabled = 0; nr_pids = 0; } *_enabled = enabled; *_pids = pids; *_nr_pids = nr_pids; return 0; }
/* * Create lttng handle and return pointer. * The returned pointer will be NULL in case of malloc() error. */ struct lttng_handle *lttng_create_handle(const char *session_name, struct lttng_domain *domain) { struct lttng_handle *handle = NULL; if (domain == NULL) { goto end; } handle = zmalloc(sizeof(struct lttng_handle)); if (handle == NULL) { PERROR("malloc handle"); goto end; } /* Copy session name */ lttng_ctl_copy_string(handle->session_name, session_name, sizeof(handle->session_name)); /* Copy lttng domain */ lttng_ctl_copy_lttng_domain(&handle->domain, domain); end: return handle; }
/* * For a given session name, this call checks if the data is ready to be read * or is still being extracted by the consumer(s) hence not ready to be used by * any readers. */ int lttng_data_pending(const char *session_name) { int ret; struct lttcomm_session_msg lsm; uint8_t *pending = NULL; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_DATA_PENDING; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pending); if (ret < 0) { goto end; } else if (ret != 1) { /* Unexpected payload size */ ret = -LTTNG_ERR_INVALID; goto end; } ret = (int) *pending; end: free(pending); return ret; }
/* * Create a session exclusively used for snapshot. * * Returns LTTNG_OK on success or a negative error code. */ int lttng_create_session_snapshot(const char *name, const char *snapshot_url) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_CREATE_SESSION_SNAPSHOT; lttng_ctl_copy_string(lsm.session.name, name, sizeof(lsm.session.name)); size = uri_parse_str_urls(snapshot_url, NULL, &uris); if (size < 0) { return -LTTNG_ERR_INVALID; } lsm.u.uri.size = size; ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); free(uris); return ret; }
int lttng_set_session_shm_path(const char *session_name, const char *shm_path) { struct lttcomm_session_msg lsm; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_SET_SESSION_SHM_PATH; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); lttng_ctl_copy_string(lsm.u.set_shm_path.shm_path, shm_path, sizeof(lsm.u.set_shm_path.shm_path)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Register an outside consumer. * Returns size of returned session payload data or a negative error code. */ int lttng_register_consumer(struct lttng_handle *handle, const char *socket_path) { struct lttcomm_session_msg lsm; if (handle == NULL || socket_path == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_REGISTER_CONSUMER; lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); lttng_ctl_copy_string(lsm.u.reg.path, socket_path, sizeof(lsm.u.reg.path)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Disable event(s) of a channel and domain. * If no event name is specified, all events are disabled. * If no channel name is specified, the default 'channel0' is used. * Returns size of returned session payload data or a negative error code. */ int lttng_disable_event(struct lttng_handle *handle, const char *name, const char *channel_name) { struct lttng_event ev; memset(&ev, 0, sizeof(ev)); ev.loglevel = -1; ev.type = LTTNG_EVENT_ALL; lttng_ctl_copy_string(ev.name, name, sizeof(ev.name)); return lttng_disable_event_ext(handle, &ev, channel_name, NULL); }
/* * All tracing will be stopped for registered events of the channel. * Returns size of returned session payload data or a negative error code. */ int lttng_disable_channel(struct lttng_handle *handle, const char *name) { struct lttcomm_session_msg lsm; /* Safety check. Both are mandatory */ if (handle == NULL || name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_DISABLE_CHANNEL; lttng_ctl_copy_string(lsm.u.disable.channel_name, name, sizeof(lsm.u.disable.channel_name)); lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * This is an extension of create session that is ONLY and SHOULD only be used * by the lttng command line program. It exists to avoid using URI parsing in * the lttng client. * * We need the date and time for the trace path subdirectory for the case where * the user does NOT define one using either -o or -U. Using the normal * lttng_create_session API call, we have no clue on the session daemon side if * the URL was generated automatically by the client or define by the user. * * So this function "wrapper" is hidden from the public API, takes the datetime * string and appends it if necessary to the URI subdirectory before sending it * to the session daemon. * * With this extra function, the lttng_create_session call behavior is not * changed and the timestamp is appended to the URI on the session daemon side * if necessary. */ int _lttng_create_session_ext(const char *name, const char *url, const char *datetime) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (name == NULL || datetime == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_CREATE_SESSION; lttng_ctl_copy_string(lsm.session.name, name, sizeof(lsm.session.name)); /* There should never be a data URL */ size = uri_parse_str_urls(url, NULL, &uris); if (size < 0) { ret = -LTTNG_ERR_INVALID; goto error; } lsm.u.uri.size = size; if (size > 0 && uris[0].dtype != LTTNG_DST_PATH && strlen(uris[0].subdir) == 0) { /* Don't append datetime if the name was automatically created. */ if (strncmp(name, DEFAULT_SESSION_NAME "-", strlen(DEFAULT_SESSION_NAME) + 1)) { ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s-%s", name, datetime); } else { ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s", name); } if (ret < 0) { PERROR("snprintf uri subdir"); ret = -LTTNG_ERR_FATAL; goto error; } } ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); error: free(uris); return ret; }
/* * Start tracing for all traces of the session. * Returns size of returned session payload data or a negative error code. */ int lttng_start_tracing(const char *session_name) { struct lttcomm_session_msg lsm; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_START_TRACE; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Destroy session using name. * Returns size of returned session payload data or a negative error code. */ int lttng_destroy_session(const char *session_name) { struct lttcomm_session_msg lsm; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_DESTROY_SESSION; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Stop tracing for all traces of the session. */ static int _lttng_stop_tracing(const char *session_name, int wait) { int ret, data_ret; struct lttcomm_session_msg lsm; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_STOP_TRACE; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); ret = lttng_ctl_ask_sessiond(&lsm, NULL); if (ret < 0 && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) { goto error; } if (!wait) { goto end; } /* Check for data availability */ do { data_ret = lttng_data_pending(session_name); if (data_ret < 0) { /* Return the data available call error. */ ret = data_ret; goto error; } /* * Data sleep time before retrying (in usec). Don't sleep if the call * returned value indicates availability. */ if (data_ret) { usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME); } } while (data_ret != 0); end: error: return ret; }
/* * Set sessiond socket path by putting it in the global sessiond_sock_path * variable. * * Returns 0 on success, negative value on failure (the sessiond socket path * is somehow too long or ENOMEM). */ static int set_session_daemon_path(void) { int in_tgroup = 0; /* In tracing group */ uid_t uid; uid = getuid(); if (uid != 0) { /* Are we in the tracing group ? */ in_tgroup = lttng_check_tracing_group(); } if ((uid == 0) || in_tgroup) { lttng_ctl_copy_string(sessiond_sock_path, DEFAULT_GLOBAL_CLIENT_UNIX_SOCK, sizeof(sessiond_sock_path)); } if (uid != 0) { int ret; if (in_tgroup) { /* Tracing group */ ret = try_connect_sessiond(sessiond_sock_path); if (ret >= 0) { goto end; } /* Global session daemon not available... */ } /* ...or not in tracing group (and not root), default */ /* * With GNU C < 2.1, snprintf returns -1 if the target buffer is too small; * With GNU C >= 2.1, snprintf returns the required size (excluding closing null) */ ret = snprintf(sessiond_sock_path, sizeof(sessiond_sock_path), DEFAULT_HOME_CLIENT_UNIX_SOCK, utils_get_home_dir()); if ((ret < 0) || (ret >= sizeof(sessiond_sock_path))) { goto error; } } end: return 0; error: return -1; }
/* * Create a session exclusively used for live. * * Returns LTTNG_OK on success or a negative error code. */ int lttng_create_session_live(const char *name, const char *url, unsigned int timer_interval) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (name == NULL || timer_interval == 0) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_CREATE_SESSION_LIVE; lttng_ctl_copy_string(lsm.session.name, name, sizeof(lsm.session.name)); if (url) { size = uri_parse_str_urls(url, NULL, &uris); if (size <= 0) { ret = -LTTNG_ERR_INVALID; goto end; } /* file:// is not accepted for live session. */ if (uris[0].dtype == LTTNG_DST_PATH) { ret = -LTTNG_ERR_INVALID; goto end; } } else { size = 0; } lsm.u.session_live.nb_uri = size; lsm.u.session_live.timer_interval = timer_interval; ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); end: free(uris); return ret; }
int lttng_save_session_attr_set_output_url( struct lttng_save_session_attr *attr, const char *url) { int ret = 0; size_t len; ssize_t size; struct lttng_uri *uris = NULL; if (!attr) { ret = -LTTNG_ERR_INVALID; goto error; } if (!url) { attr->configuration_url[0] = '\0'; ret = 0; goto end; } len = strlen(url); if (len >= PATH_MAX) { ret = -LTTNG_ERR_INVALID; goto error; } size = uri_parse_str_urls(url, NULL, &uris); if (size <= 0 || uris[0].dtype != LTTNG_DST_PATH) { ret = -LTTNG_ERR_INVALID; goto error; } /* Copy string plus the NULL terminated byte. */ lttng_ctl_copy_string(attr->configuration_url, uris[0].dst.path, sizeof(attr->configuration_url)); end: error: free(uris); return ret; }
/* * Ask the session daemon for all available domains of a session. * Sets the contents of the domains array. * Returns the number of lttng_domain entries in domains; * on error, returns a negative value. */ int lttng_list_domains(const char *session_name, struct lttng_domain **domains) { int ret; struct lttcomm_session_msg lsm; if (session_name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_LIST_DOMAINS; lttng_ctl_copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); ret = lttng_ctl_ask_sessiond(&lsm, (void**) domains); if (ret < 0) { return ret; } return ret / sizeof(struct lttng_domain); }
/* * Remove PID from session tracker. * Return 0 on success else a negative LTTng error code. */ int lttng_untrack_pid(struct lttng_handle *handle, int pid) { struct lttcomm_session_msg lsm; /* * NULL arguments are forbidden. No default values. */ if (handle == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_UNTRACK_PID; lsm.u.pid_tracker.pid = pid; lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); return lttng_ctl_ask_sessiond(&lsm, NULL); }
/* * Ask the session daemon for all available channels of a session. * Sets the contents of the channels array. * Returns the number of lttng_channel entries in channels; * on error, returns a negative value. */ int lttng_list_channels(struct lttng_handle *handle, struct lttng_channel **channels) { int ret; struct lttcomm_session_msg lsm; if (handle == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_LIST_CHANNELS; lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); ret = lttng_ctl_ask_sessiond(&lsm, (void**) channels); if (ret < 0) { return ret; } return ret / sizeof(struct lttng_channel); }
/* * Enable event(s) for a channel, possibly with exclusions and a filter. * If no event name is specified, all events are enabled. * If no channel name is specified, the default name is used. * If filter expression is not NULL, the filter is set for the event. * If exclusion count is not zero, the exclusions are set for the event. * Returns size of returned session payload data or a negative error code. */ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, struct lttng_event *ev, const char *channel_name, const char *original_filter_expression, int exclusion_count, char **exclusion_list) { struct lttcomm_session_msg lsm; char *varlen_data; int ret = 0; unsigned int free_filter_expression = 0; struct filter_parser_ctx *ctx = NULL; /* * Cast as non-const since we may replace the filter expression * by a dynamically allocated string. Otherwise, the original * string is not modified. */ char *filter_expression = (char *) original_filter_expression; if (handle == NULL || ev == NULL) { ret = -LTTNG_ERR_INVALID; goto error; } /* Empty filter string will always be rejected by the parser * anyway, so treat this corner-case early to eliminate * lttng_fmemopen error for 0-byte allocation. */ if (filter_expression && filter_expression[0] == '\0') { ret = -LTTNG_ERR_INVALID; goto error; } memset(&lsm, 0, sizeof(lsm)); /* If no channel name, send empty string. */ if (channel_name == NULL) { lttng_ctl_copy_string(lsm.u.enable.channel_name, "", sizeof(lsm.u.enable.channel_name)); } else { lttng_ctl_copy_string(lsm.u.enable.channel_name, channel_name, sizeof(lsm.u.enable.channel_name)); } lsm.cmd_type = LTTNG_ENABLE_EVENT; if (ev->name[0] == '\0') { /* Enable all events */ lttng_ctl_copy_string(ev->name, "*", sizeof(ev->name)); } lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); /* FIXME: copying non-packed struct to packed struct. */ memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event)); lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); lsm.u.enable.exclusion_count = exclusion_count; lsm.u.enable.bytecode_len = 0; /* * For the JUL domain, a filter is enforced except for the enable all * event. This is done to avoid having the event in all sessions thus * filtering by logger name. */ if (exclusion_count == 0 && filter_expression == NULL && (handle->domain.type != LTTNG_DOMAIN_JUL && handle->domain.type != LTTNG_DOMAIN_LOG4J && handle->domain.type != LTTNG_DOMAIN_PYTHON)) { goto ask_sessiond; } /* * We have either a filter or some exclusions, so we need to set up * a variable-length memory block from where to send the data */ /* Parse filter expression */ if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL || handle->domain.type == LTTNG_DOMAIN_LOG4J || handle->domain.type == LTTNG_DOMAIN_PYTHON) { if (handle->domain.type == LTTNG_DOMAIN_JUL || handle->domain.type == LTTNG_DOMAIN_LOG4J || handle->domain.type == LTTNG_DOMAIN_PYTHON) { char *agent_filter; /* Setup JUL filter if needed. */ agent_filter = set_agent_filter(filter_expression, ev); if (!agent_filter) { if (!filter_expression) { /* No JUL and no filter, just skip everything below. */ goto ask_sessiond; } } else { /* * With an agent filter, the original filter has been added to * it thus replace the filter expression. */ filter_expression = agent_filter; free_filter_expression = 1; } } ret = generate_filter(filter_expression, &lsm, &ctx); if (ret) { goto filter_error; } } varlen_data = zmalloc(lsm.u.enable.bytecode_len + lsm.u.enable.expression_len + LTTNG_SYMBOL_NAME_LEN * exclusion_count); if (!varlen_data) { ret = -LTTNG_ERR_EXCLUSION_NOMEM; goto mem_error; } /* Put exclusion names first in the data */ while (exclusion_count--) { strncpy(varlen_data + LTTNG_SYMBOL_NAME_LEN * exclusion_count, *(exclusion_list + exclusion_count), LTTNG_SYMBOL_NAME_LEN); } /* Add filter expression next */ if (lsm.u.enable.expression_len != 0) { memcpy(varlen_data + LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count, filter_expression, lsm.u.enable.expression_len); } /* Add filter bytecode next */ if (ctx && lsm.u.enable.bytecode_len != 0) { memcpy(varlen_data + LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count + lsm.u.enable.expression_len, &ctx->bytecode->b, lsm.u.enable.bytecode_len); } ret = lttng_ctl_ask_sessiond_varlen(&lsm, varlen_data, (LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count) + lsm.u.enable.bytecode_len + lsm.u.enable.expression_len, NULL); free(varlen_data); mem_error: if (filter_expression && ctx) { filter_bytecode_free(ctx); filter_ir_free(ctx); filter_parser_ctx_free(ctx); } filter_error: if (free_filter_expression) { /* * The filter expression has been replaced and must be freed as it is * not the original filter expression received as a parameter. */ free(filter_expression); } error: /* * Return directly to the caller and don't ask the sessiond since something * went wrong in the parsing of data above. */ return ret; ask_sessiond: ret = lttng_ctl_ask_sessiond(&lsm, NULL); return ret; }
struct lttng_notification_channel *lttng_notification_channel_create( struct lttng_endpoint *endpoint) { int fd, ret; bool is_in_tracing_group = false, is_root = false; char *sock_path = NULL; struct lttng_notification_channel *channel = NULL; if (!endpoint || endpoint != lttng_session_daemon_notification_endpoint) { goto end; } sock_path = zmalloc(LTTNG_PATH_MAX); if (!sock_path) { goto end; } channel = zmalloc(sizeof(struct lttng_notification_channel)); if (!channel) { goto end; } channel->socket = -1; pthread_mutex_init(&channel->lock, NULL); lttng_dynamic_buffer_init(&channel->reception_buffer); CDS_INIT_LIST_HEAD(&channel->pending_notifications.list); is_root = (getuid() == 0); if (!is_root) { is_in_tracing_group = lttng_check_tracing_group(); } if (is_root || is_in_tracing_group) { lttng_ctl_copy_string(sock_path, DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK, LTTNG_PATH_MAX); ret = lttcomm_connect_unix_sock(sock_path); if (ret >= 0) { fd = ret; goto set_fd; } } /* Fallback to local session daemon. */ ret = snprintf(sock_path, LTTNG_PATH_MAX, DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK, utils_get_home_dir()); if (ret < 0 || ret >= LTTNG_PATH_MAX) { goto error; } ret = lttcomm_connect_unix_sock(sock_path); if (ret < 0) { goto error; } fd = ret; set_fd: channel->socket = fd; ret = handshake(channel); if (ret) { goto error; } end: free(sock_path); return channel; error: lttng_notification_channel_destroy(channel); channel = NULL; goto end; }