return ret;
}
+static int check_enough_available_memory(size_t num_bytes_requested_per_cpu)
+{
+ int ret;
+ long num_cpu;
+ size_t best_mem_info;
+ size_t num_bytes_requested_total;
+
+ /*
+ * Get the number of CPU currently online to compute the amount of
+ * memory needed to create a buffer for every CPU.
+ */
+ num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
+ if (num_cpu == -1) {
+ goto error;
+ }
+
+ num_bytes_requested_total = num_bytes_requested_per_cpu * num_cpu;
+
+ /*
+ * Try to get the `MemAvail` field of `/proc/meminfo`. This is the most
+ * reliable estimate we can get but it is only exposed by the kernel
+ * since 3.14. (See Linux kernel commit:
+ * 34e431b0ae398fc54ea69ff85ec700722c9da773)
+ */
+ ret = utils_get_memory_available(&best_mem_info);
+ if (ret >= 0) {
+ goto success;
+ }
+
+ /*
+ * As a backup plan, use `MemTotal` field of `/proc/meminfo`. This
+ * is a sanity check for obvious user error.
+ */
+ ret = utils_get_memory_total(&best_mem_info);
+ if (ret >= 0) {
+ goto success;
+ }
+
+error:
+ return -1;
+success:
+ return best_mem_info >= num_bytes_requested_total;
+}
+
/*
* Try connect to session daemon with sock_path.
*
bool send_fd = false;
unsigned int free_filter_expression = 0;
struct filter_parser_ctx *ctx = NULL;
+
+ memset(&send_buffer, 0, sizeof(send_buffer));
+
/*
* Cast as non-const since we may replace the filter expression
* by a dynamically allocated string. Otherwise, the original
struct lttng_channel *in_chan)
{
struct lttcomm_session_msg lsm;
+ size_t total_buffer_size_needed_per_cpu = 0;
/* NULL arguments are forbidden. No default values. */
if (handle == NULL || in_chan == NULL) {
memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
}
+ /*
+ * Verify that the amount of memory required to create the requested
+ * buffer is available on the system at the moment.
+ */
+ total_buffer_size_needed_per_cpu = lsm.u.channel.chan.attr.num_subbuf *
+ lsm.u.channel.chan.attr.subbuf_size;
+ if (!check_enough_available_memory(total_buffer_size_needed_per_cpu)) {
+ return -LTTNG_ERR_NOMEM;
+ }
+
lsm.cmd_type = LTTNG_ENABLE_CHANNEL;
lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
goto end;
}
+ if (!cmd_header) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
/* Set number of events and free command header */
nb_events = cmd_header->nb_events;
if (nb_events > INT_MAX) {
probe_storage_req = ret;
comm_ext_at += ext_comm->userspace_probe_location_len;
- ret = 0;
}
storage_req += sizeof(struct lttng_event_extended);
ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN);
if (ret) {
ret = -LTTNG_ERR_NOMEM;
+ goto free_dynamic_buffer;
}
comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
}
int enabled = 1;
struct lttcomm_session_msg lsm;
size_t nr_pids;
- int32_t *pids;
+ int32_t *pids = NULL;
if (handle == NULL) {
return -LTTNG_ERR_INVALID;
return ret;
}
nr_pids = ret / sizeof(int32_t);
+ if (nr_pids > 0 && !pids) {
+ return -LTTNG_ERR_UNK;
+ }
if (nr_pids == 1 && pids[0] == -1) {
free(pids);
pids = NULL;
return ret;
}
-int lttng_session_get_current_archive_location(const char *session_name,
- char **chunk_path)
-{
- struct lttcomm_session_msg lsm;
- struct lttng_session_get_current_output_return *output_return = NULL;
- int ret;
- size_t path_len;
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SESSION_GET_CURRENT_OUTPUT;
- ret = lttng_strncpy(lsm.session.name, session_name,
- sizeof(lsm.session.name));
- if (ret) {
- ret = -LTTNG_ERR_INVALID;
- goto end;
- }
-
- ret = lttng_ctl_ask_sessiond(&lsm, (void **) &output_return);
- if (ret < 0) {
- ret = -1;
- goto end;
- }
-
- path_len = lttng_strnlen(output_return->path,
- sizeof(output_return->path));
- if (path_len == 0 || path_len == sizeof(output_return->path)) {
- ret = -LTTNG_ERR_NO_SESSION_OUTPUT;
- goto end;
- }
-
- *chunk_path = zmalloc(path_len + 1);
- if (!*chunk_path) {
- ret = -1;
- goto end;
- }
- memcpy(*chunk_path, output_return->path, path_len);
-
- ret = 0;
-
-end:
- free(output_return);
- return ret;
-}
-
/*
* lib constructor.
*/