From: Jonathan Rajotte Date: Mon, 18 Nov 2019 02:38:21 +0000 (-0500) Subject: Refactoring: use an opaque lttng_tracker_id type X-Git-Tag: v2.12.0-rc1~95 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=2d97a0067600335f07eecb2c1d9ba68fc164583e;p=lttng-tools.git Refactoring: use an opaque lttng_tracker_id type Move the tracker and tracker id related API to tracker.h and tracker-internal.h. The use of an opaque object mimics the new API for rotation and trigger etc. Signed-off-by: Jonathan Rajotte Change-Id: I00b876c618d7dcb0dd940189e5250c3f3d64c7e0 Signed-off-by: Jérémie Galarneau --- diff --git a/include/Makefile.am b/include/Makefile.am index ab5aa5375..610f1cb73 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -115,7 +115,8 @@ lttnginclude_HEADERS = \ lttng/session-descriptor.h \ lttng/destruction-handle.h \ lttng/clear.h \ - lttng/clear-handle.h + lttng/clear-handle.h \ + lttng/tracker.h lttngactioninclude_HEADERS= \ lttng/action/action.h \ @@ -159,5 +160,6 @@ noinst_HEADERS = \ lttng/userspace-probe-internal.h \ lttng/session-internal.h \ lttng/session-descriptor-internal.h \ + lttng/tracker-internal.h \ version.h \ version.i diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 5279bc57d..8d001a21f 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -48,6 +48,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/lttng/session.h b/include/lttng/session.h index 06d4f8b9d..b8a2b7dcc 100644 --- a/include/lttng/session.h +++ b/include/lttng/session.h @@ -25,28 +25,6 @@ extern "C" { #include -enum lttng_tracker_type { - LTTNG_TRACKER_PID = 0, - LTTNG_TRACKER_VPID = 1, - LTTNG_TRACKER_UID = 2, - LTTNG_TRACKER_GID = 3, - LTTNG_TRACKER_VUID = 4, - LTTNG_TRACKER_VGID = 5, -}; - -enum lttng_tracker_id_type { - LTTNG_ID_UNKNOWN = -1, - LTTNG_ID_ALL = 0, - LTTNG_ID_VALUE = 1, - LTTNG_ID_STRING = 2, -}; - -struct lttng_tracker_id { - enum lttng_tracker_id_type type; - int value; - char *string; -}; - struct lttng_handle; struct lttng_session_descriptor; struct lttng_destruction_handle; @@ -239,79 +217,6 @@ extern enum lttng_error_code lttng_session_get_creation_time( extern int lttng_set_session_shm_path(const char *session_name, const char *shm_path); -/* - * Add ID to session tracker. - * - * tracker_type is the type of tracker. - * id the id to track. - * - * Return 0 on success else a negative LTTng error code. - */ -extern int lttng_track_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id); - -/* - * Remove ID from session tracker. - * - * tracker_type is the type of tracker. - * id the id to untrack. - * - * Return 0 on success else a negative LTTng error code. - */ -extern int lttng_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id); - -/* - * List IDs in the tracker. - * - * tracker_type is the type of tracker. - * ids is set to an allocated array of IDs currently tracked. On - * success, ids and the strings it contains must be freed by the - * caller. - * nr_ids is set to the number of entries contained by the ids array. - * - * Returns 0 on success, else a negative LTTng error code. - */ -extern int lttng_list_tracker_ids(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - struct lttng_tracker_id **ids, - size_t *nr_ids); - -/* - * Add PID to session tracker. - * - * A pid argument >= 0 adds the PID to the session tracker. - * A pid argument of -1 means "track all PIDs". - * - * Return 0 on success else a negative LTTng error code. - */ -extern int lttng_track_pid(struct lttng_handle *handle, int pid); - -/* - * Remove PID from session tracker. - * - * A pid argument >= 0 removes the PID from the session tracker. - * A pid argument of -1 means "untrack all PIDs". - * - * Return 0 on success else a negative LTTng error code. - */ -extern int lttng_untrack_pid(struct lttng_handle *handle, int pid); - -/* - * 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. - */ -extern int lttng_list_tracker_pids(struct lttng_handle *handle, - int *enabled, int32_t **pids, size_t *nr_pids); - #ifdef __cplusplus } #endif diff --git a/include/lttng/tracker-internal.h b/include/lttng/tracker-internal.h new file mode 100644 index 000000000..a84d419d6 --- /dev/null +++ b/include/lttng/tracker-internal.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 - Jonathan Rajotte-Julien + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LTTNG_TRACKER_INTERNAL_H +#define LTTNG_TRACKER_INTERNAL_H + +#include +#include +#include +#include + +struct lttng_tracker_id { + enum lttng_tracker_id_type type; + int value; + char *string; +}; + +LTTNG_HIDDEN +bool lttng_tracker_id_is_equal(const struct lttng_tracker_id *left, + const struct lttng_tracker_id *right); + +LTTNG_HIDDEN +struct lttng_tracker_id *lttng_tracker_id_copy( + const struct lttng_tracker_id *orig); + +#endif /* LTTNG_TRACKER_INTERNAL_H */ diff --git a/include/lttng/tracker.h b/include/lttng/tracker.h new file mode 100644 index 000000000..2d952a6e3 --- /dev/null +++ b/include/lttng/tracker.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2019 - Jonathan Rajotte-Julien + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LTTNG_TRACKER_H +#define LTTNG_TRACKER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum lttng_tracker_type { + LTTNG_TRACKER_PID = 0, + LTTNG_TRACKER_VPID = 1, + LTTNG_TRACKER_UID = 2, + LTTNG_TRACKER_GID = 3, + LTTNG_TRACKER_VUID = 4, + LTTNG_TRACKER_VGID = 5, +}; + +enum lttng_tracker_id_type { + LTTNG_ID_UNKNOWN = -1, + LTTNG_ID_ALL = 0, + LTTNG_ID_VALUE = 1, + LTTNG_ID_STRING = 2, +}; + +enum lttng_tracker_id_status { + /* Invalid tracker id parameter. */ + LTTNG_TRACKER_ID_STATUS_INVALID = -1, + LTTNG_TRACKER_ID_STATUS_OK = 0, + /* Tracker id parameter is unset. */ + LTTNG_TRACKER_ID_STATUS_UNSET = 1, +}; + +struct lttng_handle; +struct lttng_tracker_id; + +/* + * Create a tracker id for the passed tracker type. + * Users must set the tracker id using the matching API call. + * + * On success, the caller is responsible for calling lttng_tracker_id_destroy. + * On error, return NULL. + */ +extern struct lttng_tracker_id *lttng_tracker_id_create(void); + +/* + * Configure the tracker id using the numerical representation of the resource + * to be tracked/untracked. + * + * If the tracker id was already configured, calling this function will replace + * the previous configuration and free memory as necessary. + * + * Returns LTTNG_TRACKER_ID_STATUS_OK on success, + * LTTNG_TRACKER_ID_STATUS_INVALID is the passed parameter is invalid. + */ +extern enum lttng_tracker_id_status lttng_tracker_id_set_value( + struct lttng_tracker_id *id, int value); + +/* + * Configure the tracker id using the string representation of the resource to + * be tracked/untracked. + * + * If the tracker id was already configured, calling this function will replace + * the previous configuration and free memory as necessary. + * + * Returns LTTNG_TRACKER_ID_STATUS_OK on success, + * LTTNG_TRACKER_ID_STATUS_INVALID if the passed parameter is invalid. + */ +extern enum lttng_tracker_id_status lttng_tracker_id_set_string( + struct lttng_tracker_id *id, const char *value); + +/* + * Configure the tracker id to track/untrack all resources for the tracker type. + * + * If the tracker id was already configured, calling this function will replace + * the previous configuration and free memory as necessary. + * + * Returns LTTNG_TRACKER_ID_STATUS_OK on success, + * LTTNG_TRACKER_ID_STATUS_INVALID if the passed parameter is invalid. + */ +extern enum lttng_tracker_id_status lttng_tracker_id_set_all( + struct lttng_tracker_id *id); + +/* + * Destroys (frees) a tracker id. + */ +extern void lttng_tracker_id_destroy(struct lttng_tracker_id *id); + +/* + * Returns the type of the tracker id. + */ +extern enum lttng_tracker_id_type lttng_tracker_id_get_type( + const struct lttng_tracker_id *id); + +/* + * Returns the value of the tracker id. + * + * Returns LTTNG_TRACKER_ID_OK on success, + * LTTNG_TRACKER_ID_STATUS_INVALID when the tracker is not of type + * LTTNG_ID_VALUE, + * LTTNG_TRACKER_ID_STATUS_UNSET when the tracker is not set. + */ +extern enum lttng_tracker_id_status lttng_tracker_id_get_value( + const struct lttng_tracker_id *id, int *value); + +/* + * Returns the string representation of the tracker id. + * + * Returns LTTNG_TRACKER_ID_OK on success, + * LTTNG_TRACKER_ID_STATUS_INVALID when the tracker is not of type + * LTTNG_ID_STRING, + * LTTNG_TRACKER_ID_STATUS_UNSET when the tracker is not set. + */ +extern enum lttng_tracker_id_status lttng_tracker_id_get_string( + const struct lttng_tracker_id *id, const char **value); + +/* + * Destroys (frees) an array of tracker id. + */ +extern void lttng_tracker_ids_destroy( + struct lttng_tracker_id **ids, size_t nr_ids); + +/* + * Add ID to session tracker. + * + * tracker_type is the type of tracker. + * id is the lttng_tracker_type to track. + * + * Returns 0 on success else a negative LTTng error code. + */ +extern int lttng_track_id(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + const struct lttng_tracker_id *id); + +/* + * Remove ID from session tracker. + * + * tracker_type is the type of tracker. + * id is the lttng_tracker_type to untrack. + * Returns 0 on success else a negative LTTng error code. + */ +extern int lttng_untrack_id(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + const struct lttng_tracker_id *id); + +/* + * List IDs in the tracker. + * + * tracker_type is the type of tracker. + * ids is set to an allocated array of IDs currently tracked. + * On success, ids must be freed using lttng_tracker_id_destroy on each + * constituent of the returned array or using lttng_tracker_ids_destroy. + * nr_ids is set to the number of entries contained by the ids array. + * + * Returns 0 on success, else a negative LTTng error code. + */ +extern int lttng_list_tracker_ids(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + struct lttng_tracker_id ***ids, + size_t *nr_ids); + +/* + * Backward compatibility. + * Add PID to session tracker. + * + * A pid argument >= 0 adds the PID to the session tracker. + * A pid argument of -1 means "track all PIDs". + * + * Returns 0 on success else a negative LTTng error code. + */ +extern int lttng_track_pid(struct lttng_handle *handle, int pid); + +/* + * Backward compatibility. + * Remove PID from session tracker. + * + * A pid argument >= 0 removes the PID from the session tracker. + * A pid argument of -1 means "untrack all PIDs". + * + * Returns 0 on success else a negative LTTng error code. + */ +extern int lttng_untrack_pid(struct lttng_handle *handle, int pid); + +/* + * Backward compatibility + * 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. + */ +extern int lttng_list_tracker_pids(struct lttng_handle *handle, + int *enabled, + int32_t **pids, + size_t *nr_pids); + +#ifdef __cplusplus +} +#endif + +#endif /* LTTNG_TRACKER_H */ diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index ae027d5e0..2c7bd4787 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -1207,98 +1207,139 @@ error_add_context: } case LTTNG_TRACK_ID: { - struct lttng_tracker_id id; + struct lttng_tracker_id *id = NULL; + enum lttng_tracker_id_status status; - memset(&id, 0, sizeof(id)); - id.type = cmd_ctx->lsm->u.id_tracker.id_type; - switch (id.type) { + id = lttng_tracker_id_create(); + if (!id) { + ret = LTTNG_ERR_NOMEM; + goto error; + } + + switch (cmd_ctx->lsm->u.id_tracker.id_type) { case LTTNG_ID_ALL: + status = lttng_tracker_id_set_all(id); break; case LTTNG_ID_VALUE: - id.value = cmd_ctx->lsm->u.id_tracker.u.value; + status = lttng_tracker_id_set_value( + id, cmd_ctx->lsm->u.id_tracker.u.value); break; case LTTNG_ID_STRING: { const size_t var_len = cmd_ctx->lsm->u.id_tracker.u.var_len; + char *string = NULL; - id.string = zmalloc(var_len); - if (!id.string) { + string = zmalloc(var_len); + if (!string) { + lttng_tracker_id_destroy(id); ret = LTTNG_ERR_NOMEM; goto error; } DBG("Receiving var len tracker id string from client"); - ret = lttcomm_recv_unix_sock(*sock, id.string, var_len); + ret = lttcomm_recv_unix_sock(*sock, string, var_len); if (ret <= 0) { DBG("Nothing received"); *sock_error = 1; - free(id.string); + free(string); + lttng_tracker_id_destroy(id); ret = LTTNG_ERR_INVALID; goto error; } - if (strnlen(id.string, var_len) != var_len - 1) { + if (strnlen(string, var_len) != var_len - 1) { DBG("String received as tracker ID is not NULL-terminated"); - free(id.string); + free(string); + lttng_tracker_id_destroy(id); ret = LTTNG_ERR_INVALID; goto error; } + + status = lttng_tracker_id_set_string(id, string); + free(string); break; } default: + lttng_tracker_id_destroy(id); ret = LTTNG_ERR_INVALID; goto error; } + + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ERR("Invalid value for tracker id"); + ret = LTTNG_ERR_INVALID; + lttng_tracker_id_destroy(id); + goto error; + } + ret = cmd_track_id(cmd_ctx->session, cmd_ctx->lsm->u.id_tracker.tracker_type, - cmd_ctx->lsm->domain.type, &id); - free(id.string); + cmd_ctx->lsm->domain.type, id); + lttng_tracker_id_destroy(id); break; } case LTTNG_UNTRACK_ID: { - struct lttng_tracker_id id; + struct lttng_tracker_id *id = NULL; + enum lttng_tracker_id_status status; + + id = lttng_tracker_id_create(); - memset(&id, 0, sizeof(id)); - id.type = cmd_ctx->lsm->u.id_tracker.id_type; - switch (id.type) { + switch (cmd_ctx->lsm->u.id_tracker.id_type) { case LTTNG_ID_ALL: + status = lttng_tracker_id_set_all(id); break; case LTTNG_ID_VALUE: - id.value = cmd_ctx->lsm->u.id_tracker.u.value; + status = lttng_tracker_id_set_value( + id, cmd_ctx->lsm->u.id_tracker.u.value); break; case LTTNG_ID_STRING: { const size_t var_len = cmd_ctx->lsm->u.id_tracker.u.var_len; + char *string = NULL; - id.string = zmalloc(var_len); - if (!id.string) { + string = zmalloc(var_len); + if (!string) { ret = LTTNG_ERR_NOMEM; + lttng_tracker_id_destroy(id); goto error; } DBG("Receiving var len tracker id string from client"); - ret = lttcomm_recv_unix_sock(*sock, id.string, var_len); + ret = lttcomm_recv_unix_sock(*sock, string, var_len); if (ret <= 0) { DBG("Nothing received"); *sock_error = 1; - free(id.string); + lttng_tracker_id_destroy(id); + free(string); ret = LTTNG_ERR_INVALID; goto error; } - if (strnlen(id.string, var_len) != var_len - 1) { + if (strnlen(string, var_len) != var_len - 1) { DBG("String received as tracker ID is not NULL-terminated"); - free(id.string); + lttng_tracker_id_destroy(id); + free(string); ret = LTTNG_ERR_INVALID; goto error; } + status = lttng_tracker_id_set_string(id, string); + free(string); break; } default: + lttng_tracker_id_destroy(id); ret = LTTNG_ERR_INVALID; goto error; } + + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ERR("Invalid tracker id"); + lttng_tracker_id_destroy(id); + ret = LTTNG_ERR_INVALID; + goto error; + } + ret = cmd_untrack_id(cmd_ctx->session, cmd_ctx->lsm->u.id_tracker.tracker_type, - cmd_ctx->lsm->domain.type, &id); - free(id.string); + cmd_ctx->lsm->domain.type, id); + lttng_tracker_id_destroy(id); break; } case LTTNG_ENABLE_EVENT: @@ -1527,7 +1568,7 @@ error_add_context: case LTTNG_LIST_TRACKER_IDS: { struct lttcomm_tracker_command_header cmd_header; - struct lttng_tracker_id *ids = NULL; + struct lttng_tracker_id **ids = NULL; ssize_t nr_ids, i; struct lttng_dynamic_buffer buf; @@ -1543,44 +1584,60 @@ error_add_context: lttng_dynamic_buffer_init(&buf); for (i = 0; i < nr_ids; i++) { - struct lttng_tracker_id *id = &ids[i]; + struct lttng_tracker_id *id = ids[i]; struct lttcomm_tracker_id_header id_hdr; size_t var_data_len = 0; + enum lttng_tracker_id_status status; + const char *string; + int value; memset(&id_hdr, 0, sizeof(id_hdr)); - id_hdr.type = id->type; - switch (id->type) { + id_hdr.type = lttng_tracker_id_get_type(id); + switch (id_hdr.type) { case LTTNG_ID_ALL: break; case LTTNG_ID_VALUE: - id_hdr.u.value = id->value; + status = lttng_tracker_id_get_value(id, &value); + id_hdr.u.value = value; + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = LTTNG_ERR_INVALID; + goto error_list_tracker; + } break; case LTTNG_ID_STRING: + status = lttng_tracker_id_get_string( + id, &string); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = LTTNG_ERR_INVALID; + goto error_list_tracker; + } + id_hdr.u.var_data_len = var_data_len = - strlen(id->string) + 1; + strlen(string) + 1; break; default: ret = LTTNG_ERR_INVALID; - goto error; + goto error_list_tracker; } ret = lttng_dynamic_buffer_append( &buf, &id_hdr, sizeof(id_hdr)); if (ret) { ret = LTTNG_ERR_NOMEM; - goto error; + goto error_list_tracker; } ret = lttng_dynamic_buffer_append( - &buf, id->string, var_data_len); + &buf, string, var_data_len); if (ret) { ret = LTTNG_ERR_NOMEM; - goto error; + goto error_list_tracker; } - free(id->string); } cmd_header.nb_tracker_id = nr_ids; ret = setup_lttng_msg(cmd_ctx, buf.data, buf.size, &cmd_header, sizeof(cmd_header)); + error_list_tracker: + lttng_tracker_ids_destroy(ids, nr_ids); free(ids); lttng_dynamic_buffer_reset(&buf); if (ret < 0) { diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index f152c1c2e..b668b56d4 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -2584,7 +2584,7 @@ ssize_t cmd_list_syscalls(struct lttng_event **events) ssize_t cmd_list_tracker_ids(enum lttng_tracker_type tracker_type, struct ltt_session *session, enum lttng_domain_type domain, - struct lttng_tracker_id **ids) + struct lttng_tracker_id ***ids) { int ret; ssize_t nr_pids = 0; diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 9329f42cf..ee4bf65e7 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -117,7 +117,7 @@ ssize_t cmd_list_syscalls(struct lttng_event **events); ssize_t cmd_list_tracker_ids(enum lttng_tracker_type tracker_type, struct ltt_session *session, enum lttng_domain_type domain, - struct lttng_tracker_id **ids); + struct lttng_tracker_id ***ids); int cmd_data_pending(struct ltt_session *session); diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 113937536..c5fd30b7e 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -707,8 +707,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, { int ret, value; struct lttng_tracker_list *tracker_list; - struct lttng_tracker_id *saved_ids; - ssize_t saved_ids_count, i; + struct lttng_tracker_id **saved_ids; + ssize_t saved_ids_count; ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); if (ret != LTTNG_OK) { @@ -813,9 +813,7 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, ERR("Error on tracker add error handling.\n"); } end: - for (i = 0; i < saved_ids_count; i++) { - free(saved_ids[i].string); - } + lttng_tracker_ids_destroy(saved_ids, saved_ids_count); free(saved_ids); return ret; } @@ -826,8 +824,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, { int ret, value; struct lttng_tracker_list *tracker_list; - struct lttng_tracker_id *saved_ids; - ssize_t saved_ids_count, i; + struct lttng_tracker_id **saved_ids; + ssize_t saved_ids_count; ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); if (ret != LTTNG_OK) { @@ -933,9 +931,7 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, ERR("Error on tracker remove error handling.\n"); } end: - for (i = 0; i < saved_ids_count; i++) { - free(saved_ids[i].string); - } + lttng_tracker_ids_destroy(saved_ids, saved_ids_count); free(saved_ids); return ret; } @@ -945,7 +941,7 @@ end: */ ssize_t kernel_list_tracker_ids(enum lttng_tracker_type tracker_type, struct ltt_kernel_session *session, - struct lttng_tracker_id **_ids) + struct lttng_tracker_id ***_ids) { struct lttng_tracker_list *tracker_list; diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index cf91cab1b..64d95d235 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -74,7 +74,7 @@ enum lttng_error_code kernel_clear_session(struct ltt_session *session); int init_kernel_workarounds(void); ssize_t kernel_list_tracker_ids(enum lttng_tracker_type tracker_type, struct ltt_kernel_session *session, - struct lttng_tracker_id **_ids); + struct lttng_tracker_id ***_ids); int kernel_supports_ring_buffer_snapshot_sample_positions(void); int kernel_supports_ring_buffer_packet_sequence_number(void); int init_kernel_tracer(void); diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 59715d0b9..83019842d 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -1837,8 +1837,12 @@ static int save_id_tracker(struct config_writer *writer, { int ret = LTTNG_OK; ssize_t nr_ids = 0, i; - struct lttng_tracker_id *ids = NULL; + struct lttng_tracker_id **ids = NULL; const char *element_id_tracker, *element_target_id, *element_id; + struct lttng_tracker_id *id; + enum lttng_tracker_id_status status; + int value; + const char *string; switch (tracker_type) { case LTTNG_TRACKER_PID: @@ -1905,7 +1909,7 @@ static int save_id_tracker(struct config_writer *writer, goto end; } - if (nr_ids == 1 && ids[0].type == LTTNG_ID_ALL) { + if (nr_ids == 1 && lttng_tracker_id_get_type(ids[0]) == LTTNG_ID_ALL) { /* Tracking all, nothing to output. */ ret = LTTNG_OK; goto end; @@ -1940,7 +1944,8 @@ static int save_id_tracker(struct config_writer *writer, } else { /* Tracking list. */ for (i = 0; i < nr_ids; i++) { - switch (ids[i].type) { + id = ids[i]; + switch (lttng_tracker_id_get_type(id)) { case LTTNG_ID_VALUE: ret = config_writer_open_element( writer, element_target_id); @@ -1948,9 +1953,9 @@ static int save_id_tracker(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + status = lttng_tracker_id_get_value(id, &value); ret = config_writer_write_element_unsigned_int( - writer, element_id, - ids[i].value); + writer, element_id, value); break; case LTTNG_ID_STRING: ret = config_writer_open_element( @@ -1959,9 +1964,10 @@ static int save_id_tracker(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + status = lttng_tracker_id_get_string( + id, &string); ret = config_writer_write_element_string(writer, - config_element_name, - ids[i].string); + config_element_name, string); break; default: /* Unexpected. */ @@ -1972,6 +1978,10 @@ static int save_id_tracker(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } /* /$element_target_id */ ret = config_writer_close_element(writer); @@ -1998,6 +2008,7 @@ static int save_id_tracker(struct config_writer *writer, ret = LTTNG_OK; end: + lttng_tracker_ids_destroy(ids, nr_ids); free(ids); return ret; } diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index f64f51c28..4a7e26105 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -918,8 +918,8 @@ int trace_ust_track_id(enum lttng_tracker_type tracker_type, struct ust_id_tracker *id_tracker; struct lttng_tracker_list *tracker_list; int value; - struct lttng_tracker_id *saved_ids; - ssize_t saved_ids_count, i; + struct lttng_tracker_id **saved_ids; + ssize_t saved_ids_count; if (tracker_type == LTTNG_TRACKER_PID) { DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); @@ -1002,9 +1002,7 @@ end_restore: ERR("Error on tracker add error handling.\n"); } end: - for (i = 0; i < saved_ids_count; i++) { - free(saved_ids[i].string); - } + lttng_tracker_ids_destroy(saved_ids, saved_ids_count); free(saved_ids); return retval; } @@ -1021,8 +1019,8 @@ int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, struct ust_id_tracker *id_tracker; struct lttng_tracker_list *tracker_list; int value; - struct lttng_tracker_id *saved_ids; - ssize_t saved_ids_count, i; + struct lttng_tracker_id **saved_ids; + ssize_t saved_ids_count; if (tracker_type == LTTNG_TRACKER_PID) { DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); @@ -1107,9 +1105,7 @@ end_restore: ERR("Error on tracker remove error handling.\n"); } end: - for (i = 0; i < saved_ids_count; i++) { - free(saved_ids[i].string); - } + lttng_tracker_ids_destroy(saved_ids, saved_ids_count); free(saved_ids); return retval; } @@ -1119,7 +1115,7 @@ end: */ ssize_t trace_ust_list_tracker_ids(enum lttng_tracker_type tracker_type, struct ltt_ust_session *session, - struct lttng_tracker_id **_ids) + struct lttng_tracker_id ***_ids) { struct lttng_tracker_list *tracker_list; diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index 1f6f534fe..2d0b042e5 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -240,7 +240,7 @@ int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type, ssize_t trace_ust_list_tracker_ids(enum lttng_tracker_type tracker_type, struct ltt_ust_session *session, - struct lttng_tracker_id **_ids); + struct lttng_tracker_id ***_ids); #else /* HAVE_LIBLTTNG_UST_CTL */ diff --git a/src/bin/lttng-sessiond/tracker.c b/src/bin/lttng-sessiond/tracker.c index af527b4fd..909a04845 100644 --- a/src/bin/lttng-sessiond/tracker.c +++ b/src/bin/lttng-sessiond/tracker.c @@ -27,6 +27,7 @@ #include #include #include +#include #define FALLBACK_USER_BUFLEN 16384 #define FALLBACK_GROUP_BUFLEN 16384 @@ -60,53 +61,42 @@ static int match_tracker_key(struct cds_lfht_node *node, const void *key) tracker_node = caa_container_of( node, struct lttng_tracker_list_node, ht_node); - if (tracker_node->id.type != tracker_key->type) { - return 0; - } - switch (tracker_node->id.type) { - case LTTNG_ID_ALL: - return 1; - case LTTNG_ID_VALUE: - if (tracker_node->id.value != tracker_key->value) { - return 0; - } - break; - case LTTNG_ID_STRING: - if (strcmp(tracker_node->id.string, tracker_key->string) != 0) { - return 0; - } - break; - default: - return 0; - } - return 1; + + return lttng_tracker_id_is_equal(tracker_node->id, tracker_key); } static unsigned long hash_tracker_key( const struct lttng_tracker_id *tracker_key) { unsigned long key_hash = 0; + int value; + const char *string; + enum lttng_tracker_id_type type; + + /* We do not care for invalid state during hash computation */ + type = lttng_tracker_id_get_type(tracker_key); + (void) lttng_tracker_id_get_value(tracker_key, &value); + (void) lttng_tracker_id_get_string(tracker_key, &string); - switch (tracker_key->type) { + switch (type) { case LTTNG_ID_ALL: break; case LTTNG_ID_VALUE: key_hash ^= hash_key_ulong( - (void *) (unsigned long) tracker_key->value, - lttng_ht_seed); + (void *) (unsigned long) value, lttng_ht_seed); break; case LTTNG_ID_STRING: - key_hash ^= hash_key_str(tracker_key->string, lttng_ht_seed); + key_hash ^= hash_key_str(string, lttng_ht_seed); break; case LTTNG_ID_UNKNOWN: break; } - key_hash ^= hash_key_ulong((void *) (unsigned long) tracker_key->type, - lttng_ht_seed); + key_hash ^= hash_key_ulong( + (void *) (unsigned long) type, lttng_ht_seed); return key_hash; } -static struct lttng_tracker_id *lttng_tracker_list_lookup( +static struct lttng_tracker_id **lttng_tracker_list_lookup( const struct lttng_tracker_list *tracker_list, const struct lttng_tracker_id *key) { @@ -130,7 +120,7 @@ static void destroy_list_node_rcu(struct rcu_head *head) struct lttng_tracker_list_node *n = caa_container_of( head, struct lttng_tracker_list_node, rcu_head); - free(n->id.string); + lttng_tracker_id_destroy(n->id); free(n); } @@ -161,14 +151,15 @@ static void lttng_tracker_list_reset(struct lttng_tracker_list *tracker_list) int lttng_tracker_list_add(struct lttng_tracker_list *tracker_list, const struct lttng_tracker_id *_id) { - struct lttng_tracker_id *id; - struct lttng_tracker_list_node *n; + struct lttng_tracker_id **id; + struct lttng_tracker_list_node *n = NULL; int ret; - if (_id->type == LTTNG_ID_ALL) { + if (lttng_tracker_id_get_type(_id) == LTTNG_ID_ALL) { /* Track all, so remove each individual item. */ lttng_tracker_list_reset(tracker_list); - return LTTNG_OK; + ret = LTTNG_OK; + goto error; } rcu_read_lock(); id = lttng_tracker_list_lookup(tracker_list, _id); @@ -178,28 +169,26 @@ int lttng_tracker_list_add(struct lttng_tracker_list *tracker_list, */ rcu_read_unlock(); if (id) { - return LTTNG_ERR_ID_TRACKED; + ret = LTTNG_ERR_ID_TRACKED; + goto error; } n = zmalloc(sizeof(*n)); if (!n) { - return LTTNG_ERR_NOMEM; + ret = LTTNG_ERR_NOMEM; + goto error; } - n->id = *_id; - if (_id->type == LTTNG_ID_STRING) { - n->id.string = strdup(_id->string); - if (!n->id.string) { - ret = LTTNG_ERR_NOMEM; - goto error; - } - } else { - n->id.string = NULL; + + n->id = lttng_tracker_id_copy(_id); + if (!n->id) { + ret = LTTNG_ERR_NOMEM; + goto error; } cds_list_add_tail(&n->list_node, &tracker_list->list_head); tracker_list->state = LTTNG_TRACK_LIST; rcu_read_lock(); - cds_lfht_add(tracker_list->ht, hash_tracker_key(&n->id), &n->ht_node); + cds_lfht_add(tracker_list->ht, hash_tracker_key(n->id), &n->ht_node); rcu_read_unlock(); return LTTNG_OK; @@ -217,10 +206,10 @@ int lttng_tracker_list_remove(struct lttng_tracker_list *tracker_list, const struct lttng_tracker_id *_id) { enum lttng_error_code ret = LTTNG_OK; - struct lttng_tracker_id *id; + struct lttng_tracker_id **id; struct lttng_tracker_list_node *n; - if (_id->type == LTTNG_ID_ALL) { + if (lttng_tracker_id_get_type(_id) == LTTNG_ID_ALL) { /* Untrack all. */ lttng_tracker_list_reset(tracker_list); /* Set state to "track none". */ @@ -380,14 +369,26 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type, const struct lttng_tracker_id *id, int *result) { - switch (id->type) { + enum lttng_tracker_id_status status; + int value; + const char *string; + + switch (lttng_tracker_id_get_type(id)) { case LTTNG_ID_ALL: *result = -1; return LTTNG_OK; case LTTNG_ID_VALUE: + status = lttng_tracker_id_get_value(id, &value); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + return LTTNG_ERR_INVALID; + } *result = id->value; return LTTNG_OK; case LTTNG_ID_STRING: + status = lttng_tracker_id_get_string(id, &string); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + return LTTNG_ERR_INVALID; + } switch (tracker_type) { case LTTNG_TRACKER_PID: case LTTNG_TRACKER_VPID: @@ -396,11 +397,11 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type, case LTTNG_TRACKER_UID: case LTTNG_TRACKER_VUID: DBG("Lookup of tracker UID/VUID by name."); - return lttng_lookup_user(id->string, result); + return lttng_lookup_user(string, result); case LTTNG_TRACKER_GID: case LTTNG_TRACKER_VGID: DBG("Lookup of tracker GID/VGID by name."); - return lttng_lookup_group(id->string, result); + return lttng_lookup_group(string, result); default: return LTTNG_ERR_INVALID; } @@ -412,14 +413,15 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type, /* * Protected by session mutex held by caller. - * On success, _ids and the strings it contains must be freed by caller. + * On success, _ids and the ids it contains must be freed by the caller. */ ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list, - struct lttng_tracker_id **_ids) + struct lttng_tracker_id ***_ids) { struct lttng_tracker_list_node *n; ssize_t count = 0, i = 0, retval = 0; - struct lttng_tracker_id *ids; + struct lttng_tracker_id **ids; + enum lttng_tracker_id_status status; switch (tracker_list->state) { case LTTNG_TRACK_LIST: @@ -435,14 +437,10 @@ ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list, } cds_list_for_each_entry ( n, &tracker_list->list_head, list_node) { - ids[i].type = n->id.type; - ids[i].value = n->id.value; - if (ids[i].type == LTTNG_ID_STRING) { - ids[i].string = strdup(n->id.string); - if (!ids[i].string) { - retval = -LTTNG_ERR_NOMEM; - goto error; - } + ids[i] = lttng_tracker_id_copy(n->id); + if (!ids[i]) { + retval = -LTTNG_ERR_NOMEM; + goto error; } i++; } @@ -456,7 +454,13 @@ ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list, retval = -LTTNG_ERR_NOMEM; goto end; } - ids->type = LTTNG_TRACK_ALL; + ids[0] = lttng_tracker_id_create(); + status = lttng_tracker_id_set_all(ids[0]); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ERR("Invalid tracker id for track all"); + retval = -LTTNG_ERR_INVALID; + goto error; + } *_ids = ids; retval = 1; break; @@ -469,21 +473,19 @@ end: return retval; error: - for (i = 0; i < count; i++) { - free(ids[i].string); - } + lttng_tracker_ids_destroy(ids, count); free(ids); return retval; } int lttng_tracker_id_set_list(struct lttng_tracker_list *tracker_list, - struct lttng_tracker_id *_ids, + struct lttng_tracker_id **_ids, size_t count) { size_t i; lttng_tracker_list_reset(tracker_list); - if (count == 1 && _ids[0].type == LTTNG_ID_ALL) { + if (count == 1 && lttng_tracker_id_get_type(_ids[0])) { /* Track all. */ return LTTNG_OK; } @@ -493,7 +495,7 @@ int lttng_tracker_id_set_list(struct lttng_tracker_list *tracker_list, return LTTNG_OK; } for (i = 0; i < count; i++) { - struct lttng_tracker_id *id = &_ids[i]; + struct lttng_tracker_id *id = _ids[i]; int ret; ret = lttng_tracker_list_add(tracker_list, id); diff --git a/src/bin/lttng-sessiond/tracker.h b/src/bin/lttng-sessiond/tracker.h index 1df4a0ce7..812b3b127 100644 --- a/src/bin/lttng-sessiond/tracker.h +++ b/src/bin/lttng-sessiond/tracker.h @@ -18,7 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include +#include #include #include #include @@ -31,7 +31,7 @@ enum lttng_tracker_list_state { /* Tracker ID */ struct lttng_tracker_list_node { - struct lttng_tracker_id id; + struct lttng_tracker_id *id; struct cds_list_head list_node; struct cds_lfht_node ht_node; @@ -57,9 +57,9 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type, const struct lttng_tracker_id *id, int *result); ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list, - struct lttng_tracker_id **_ids); + struct lttng_tracker_id ***_ids); int lttng_tracker_id_set_list(struct lttng_tracker_list *tracker_list, - struct lttng_tracker_id *_ids, + struct lttng_tracker_id **_ids, size_t count); #endif /* _LTT_TRACKER_H */ diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 226eb4c87..49470ab86 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "../command.h" @@ -1538,14 +1539,14 @@ static int list_tracker_ids(enum lttng_tracker_type tracker_type) { int ret = 0; int enabled = 1; - struct lttng_tracker_id *ids = NULL; + struct lttng_tracker_id **ids = NULL; size_t nr_ids, i; ret = lttng_list_tracker_ids(handle, tracker_type, &ids, &nr_ids); if (ret) { return ret; } - if (nr_ids == 1 && ids[0].type == LTTNG_ID_ALL) { + if (nr_ids == 1 && lttng_tracker_id_get_type(ids[0]) == LTTNG_ID_ALL) { enabled = 0; } if (enabled) { @@ -1561,23 +1562,49 @@ static int list_tracker_ids(enum lttng_tracker_type tracker_type) } for (i = 0; i < nr_ids; i++) { - struct lttng_tracker_id *id = &ids[i]; + struct lttng_tracker_id *id = ids[i]; + enum lttng_tracker_id_status status; + int value; + const char *value_string; + + switch (lttng_tracker_id_get_type(id)) { + case LTTNG_ID_ALL: + break; + case LTTNG_ID_VALUE: + status = lttng_tracker_id_get_value(id, &value); + break; + case LTTNG_ID_STRING: + status = lttng_tracker_id_get_string( + id, &value_string); + break; + case LTTNG_ID_UNKNOWN: + ret = CMD_ERROR; + goto end; + } + + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ERR("Invalid state for tracker id"); + ret = CMD_ERROR; + goto end; + } if (i) { _MSG(","); } - switch (id->type) { + switch (lttng_tracker_id_get_type(id)) { case LTTNG_ID_ALL: _MSG(" *"); break; case LTTNG_ID_VALUE: - _MSG(" %d", ids[i].value); + _MSG(" %d", value); break; case LTTNG_ID_STRING: - _MSG(" %s", ids[i].string); + _MSG(" %s", value_string); break; case LTTNG_ID_UNKNOWN: - return CMD_ERROR; + ERR("Invalid state for tracker id"); + ret = CMD_ERROR; + goto end; } /* Mi */ @@ -1600,10 +1627,7 @@ static int list_tracker_ids(enum lttng_tracker_type tracker_type) } } end: - for (i = 0; i < nr_ids; i++) { - free(ids[i].string); - } - free(ids); + lttng_tracker_ids_destroy(ids, nr_ids); return ret; } diff --git a/src/bin/lttng/commands/track-untrack.c b/src/bin/lttng/commands/track-untrack.c index 25b4461f6..c54b64078 100644 --- a/src/bin/lttng/commands/track-untrack.c +++ b/src/bin/lttng/commands/track-untrack.c @@ -56,7 +56,7 @@ struct opt_type { struct id_list { size_t nr; - struct lttng_tracker_id *array; + struct lttng_tracker_id **array; }; static char *opt_session_name; @@ -100,7 +100,7 @@ static struct poptOption long_options[] = { static struct id_list *alloc_id_list(size_t nr_items) { struct id_list *id_list; - struct lttng_tracker_id *items; + struct lttng_tracker_id **items; id_list = zmalloc(sizeof(*id_list)); if (!id_list) { @@ -128,15 +128,16 @@ static void free_id_list(struct id_list *list) } nr_items = list->nr; for (i = 0; i < nr_items; i++) { - struct lttng_tracker_id *item = &list->array[i]; - - free(item->string); + struct lttng_tracker_id *item = list->array[i]; + lttng_tracker_id_destroy(item); } free(list); } -static int parse_id_string( - const char *_id_string, int all, struct id_list **_id_list) +static int parse_id_string(const char *_id_string, + int all, + struct id_list **_id_list, + enum lttng_tracker_type tracker_type) { const char *one_id_str; char *iter; @@ -157,14 +158,28 @@ static int parse_id_string( goto error; } if (all) { - /* Empty ID string means all IDs */ + enum lttng_tracker_id_status status; + /* Empty `ID string means all IDs */ id_list = alloc_id_list(1); if (!id_list) { ERR("Out of memory"); retval = CMD_ERROR; goto error; } - id_list->array[0].type = LTTNG_ID_ALL; + + id_list->array[0] = lttng_tracker_id_create(); + if (id_list->array[0] == NULL) { + ERR("Out of memory"); + retval = CMD_ERROR; + goto error; + } + + status = lttng_tracker_id_set_all(id_list->array[0]); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ERR("Invalid value for tracker id"); + retval = CMD_ERROR; + goto error; + } goto assign; } @@ -230,20 +245,30 @@ static int parse_id_string( count = 0; one_id_str = strtok_r(id_string, ",", &iter); while (one_id_str != NULL) { + enum lttng_tracker_id_status status; struct lttng_tracker_id *item; + item = lttng_tracker_id_create(); + if (item == NULL) { + ERR("Out of memory"); + retval = CMD_ERROR; + goto error; + } - item = &id_list->array[count++]; + id_list->array[count++] = item; if (isdigit(one_id_str[0])) { unsigned long v; v = strtoul(one_id_str, NULL, 10); - item->type = LTTNG_ID_VALUE; - item->value = (int) v; + status = lttng_tracker_id_set_value(item, (int) v); + if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { + ERR("Invalid value"); + retval = CMD_ERROR; + goto error; + } } else { - item->type = LTTNG_ID_STRING; - item->string = strdup(one_id_str); - if (!item->string) { - PERROR("Failed to allocate ID string"); + status = lttng_tracker_id_set_string(item, one_id_str); + if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { + ERR("Failed to set ID string"); retval = CMD_ERROR; goto error; } @@ -254,11 +279,12 @@ static int parse_id_string( } assign: + /* SUCCESS */ *_id_list = id_list; - goto end; /* SUCCESS */ + goto end; - /* ERROR */ error: + /* ERROR */ free_id_list(id_list); end: free(id_string); @@ -365,7 +391,7 @@ static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, retval = CMD_ERROR; goto end; } - ret = parse_id_string(id_string, all, &id_list); + ret = parse_id_string(id_string, all, &id_list, tracker_type); if (ret != CMD_SUCCESS) { ERR("Error parsing %s string", tracker_str); retval = CMD_ERROR; @@ -387,22 +413,51 @@ static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, } for (i = 0; i < id_list->nr; i++) { - struct lttng_tracker_id *item = &id_list->array[i]; + struct lttng_tracker_id *item = id_list->array[i]; + enum lttng_tracker_id_type type = + lttng_tracker_id_get_type(item); + enum lttng_tracker_id_status status = + LTTNG_TRACKER_ID_STATUS_OK; + int value; + const char *value_string; + + switch (type) { + case LTTNG_ID_ALL: + /* Nothing to check */ + break; + case LTTNG_ID_VALUE: + status = lttng_tracker_id_get_value(item, &value); + break; + case LTTNG_ID_STRING: + status = lttng_tracker_id_get_string( + item, &value_string); + break; + default: + retval = CMD_ERROR; + goto end; + } - switch (item->type) { + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ERR("Tracker id object is in an invalid state"); + retval = CMD_ERROR; + goto end; + } + + switch (type) { case LTTNG_ID_ALL: DBG("%s all IDs", cmd_str); break; case LTTNG_ID_VALUE: - DBG("%s ID %d", cmd_str, item->value); + DBG("%s ID %d", cmd_str, value); break; case LTTNG_ID_STRING: - DBG("%s ID '%s'", cmd_str, item->string); + DBG("%s ID '%s'", cmd_str, value_string); break; default: retval = CMD_ERROR; goto end; } + ret = cmd_func(handle, tracker_type, item); if (ret) { char *msg = NULL; @@ -425,7 +480,7 @@ static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, break; } if (msg) { - switch (item->type) { + switch (type) { case LTTNG_ID_ALL: WARN("All %ss %s in session %s", tracker_str, msg, @@ -433,14 +488,13 @@ static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, break; case LTTNG_ID_VALUE: WARN("%s %i %s in session %s", - tracker_str, - item->value, msg, + tracker_str, value, msg, session_name); break; case LTTNG_ID_STRING: WARN("%s '%s' %s in session %s", tracker_str, - item->string, msg, + value_string, msg, session_name); break; default: @@ -449,19 +503,18 @@ static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, } } } else { - switch (item->type) { + switch (type) { case LTTNG_ID_ALL: MSG("All %ss %sed in session %s", tracker_str, cmd_str, session_name); break; case LTTNG_ID_VALUE: MSG("%s %i %sed in session %s", tracker_str, - item->value, cmd_str, - session_name); + value, cmd_str, session_name); break; case LTTNG_ID_STRING: MSG("%s '%s' %sed in session %s", tracker_str, - item->string, cmd_str, + value_string, cmd_str, session_name); break; default: diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 95935b76e..e7ceefe47 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -62,6 +62,7 @@ libcommon_la_SOURCES = \ userspace-probe.c \ utils.c utils.h \ uuid.c uuid.h \ + tracker.c \ waiter.c waiter.h if HAVE_ELF_H diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c index e625f316a..695142a29 100644 --- a/src/common/config/session-config.c +++ b/src/common/config/session-config.c @@ -2745,6 +2745,7 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, const char *element_id; const char *element_id_alias; const char *element_name; + enum lttng_tracker_id_status status; assert(handle); assert(id_tracker_node); @@ -2774,11 +2775,21 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, /* Go through all id target node */ child = xmlChildElementCount(targets_node); if (child == 0) { - struct lttng_tracker_id tracker_id; + struct lttng_tracker_id *tracker_id = NULL; + tracker_id = lttng_tracker_id_create(); + if (tracker_id == NULL) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + status = lttng_tracker_id_set_all(tracker_id); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = LTTNG_ERR_INVALID; + goto end; + } - tracker_id.type = LTTNG_ID_ALL; /* The session is explicitly set to target nothing. */ - ret = lttng_untrack_id(handle, tracker_type, &tracker_id); + ret = lttng_untrack_id(handle, tracker_type, tracker_id); + lttng_tracker_id_destroy(tracker_id); if (ret) { goto end; } @@ -2796,7 +2807,7 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, element_id_alias))) { int64_t id; xmlChar *content = NULL; - struct lttng_tracker_id tracker_id; + struct lttng_tracker_id *tracker_id = NULL; content = xmlNodeGetContent(node); if (!content) { @@ -2811,10 +2822,23 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, goto end; } - tracker_id.type = LTTNG_ID_VALUE; - tracker_id.value = (int) id; + tracker_id = lttng_tracker_id_create(); + if (tracker_id == NULL) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + + status = lttng_tracker_id_set_value( + tracker_id, id); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + lttng_tracker_id_destroy(tracker_id); + ret = LTTNG_ERR_LOAD_INVALID_CONFIG; + goto end; + } + ret = lttng_track_id(handle, tracker_type, - &tracker_id); + tracker_id); + lttng_tracker_id_destroy(tracker_id); if (ret) { goto end; } @@ -2822,17 +2846,31 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, if (element_name && !strcmp((const char *) node->name, element_name)) { xmlChar *content = NULL; - struct lttng_tracker_id tracker_id; + struct lttng_tracker_id *tracker_id = NULL; content = xmlNodeGetContent(node); if (!content) { ret = LTTNG_ERR_LOAD_INVALID_CONFIG; goto end; } - tracker_id.type = LTTNG_ID_STRING; - tracker_id.string = (char *) content; + + tracker_id = lttng_tracker_id_create(); + if (tracker_id == NULL) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + + status = lttng_tracker_id_set_string(tracker_id, + (const char *) content); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + lttng_tracker_id_destroy(tracker_id); + ret = LTTNG_ERR_LOAD_INVALID_CONFIG; + goto end; + } + ret = lttng_track_id(handle, tracker_type, - &tracker_id); + tracker_id); + lttng_tracker_id_destroy(tracker_id); free(content); if (ret) { goto end; diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index f884f9385..7b0d9cf02 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "mi-lttng.h" @@ -1666,6 +1667,9 @@ int mi_lttng_id_target(struct mi_writer *writer, { int ret; const char *element_id_tracker, *element_target_id; + enum lttng_tracker_id_status status; + int value; + const char *string; ret = get_tracker_elements( tracker_type, &element_id_tracker, &element_target_id); @@ -1673,7 +1677,7 @@ int mi_lttng_id_target(struct mi_writer *writer, return ret; } - switch (id->type) { + switch (lttng_tracker_id_get_type(id)) { case LTTNG_ID_ALL: ret = mi_lttng_writer_open_element(writer, element_target_id); if (ret) { @@ -1702,8 +1706,15 @@ int mi_lttng_id_target(struct mi_writer *writer, if (ret) { goto end; } + + status = lttng_tracker_id_get_value(id, &value); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = -1; + goto end; + } + ret = mi_lttng_writer_write_element_signed_int( - writer, config_element_id, id->value); + writer, config_element_id, value); if (ret) { goto end; } @@ -1721,8 +1732,15 @@ int mi_lttng_id_target(struct mi_writer *writer, if (ret) { goto end; } + + status = lttng_tracker_id_get_string(id, &string); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = -1; + goto end; + } + ret = mi_lttng_writer_write_element_string( - writer, config_element_name, id->string); + writer, config_element_name, string); if (ret) { goto end; } diff --git a/src/common/tracker.c b/src/common/tracker.c new file mode 100644 index 000000000..f8a4fba0f --- /dev/null +++ b/src/common/tracker.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2019 - Jonathan Rajotte-Julien + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct lttng_tracker_id *lttng_tracker_id_create(void) +{ + struct lttng_tracker_id *id; + + id = zmalloc(sizeof(*id)); + if (!id) { + goto error; + } + + id->type = LTTNG_ID_UNKNOWN; + id->string = NULL; + id->value = -1; + return id; +error: + lttng_tracker_id_destroy(id); + return NULL; +} + +enum lttng_tracker_id_status lttng_tracker_id_set_value( + struct lttng_tracker_id *id, int value) +{ + assert(id); + + if (value < 0) { + return LTTNG_TRACKER_ID_STATUS_INVALID; + } + + id->type = LTTNG_ID_VALUE; + id->value = value; + return LTTNG_TRACKER_ID_STATUS_OK; +} + +enum lttng_tracker_id_status lttng_tracker_id_set_string( + struct lttng_tracker_id *id, const char *value) +{ + assert(id); + assert(value); + + id->type = LTTNG_ID_STRING; + id->string = strdup(value); + if (id->string == NULL) { + /* No memory left */ + goto error; + } + + return LTTNG_TRACKER_ID_STATUS_OK; +error: + return LTTNG_TRACKER_ID_STATUS_INVALID; +} + +enum lttng_tracker_id_status lttng_tracker_id_set_all( + struct lttng_tracker_id *id) +{ + assert(id); + + id->type = LTTNG_ID_ALL; + + return LTTNG_TRACKER_ID_STATUS_OK; +} + +void lttng_tracker_id_destroy(struct lttng_tracker_id *id) +{ + if (id == NULL) { + return; + } + + if (id->string != NULL) { + free(id->string); + } + + free(id); +} + +void lttng_tracker_ids_destroy(struct lttng_tracker_id **ids, size_t nr_ids) +{ + if (ids == NULL) { + return; + } + + for (int i = 0; i < nr_ids; i++) { + lttng_tracker_id_destroy(ids[i]); + } +} + +enum lttng_tracker_id_type lttng_tracker_id_get_type( + const struct lttng_tracker_id *id) +{ + assert(id); + return id->type; +} + +enum lttng_tracker_id_status lttng_tracker_id_get_value( + const struct lttng_tracker_id *id, int *value) +{ + assert(id); + if (id->type == LTTNG_ID_UNKNOWN) { + return LTTNG_TRACKER_ID_STATUS_UNSET; + } + + if (id->type != LTTNG_ID_VALUE) { + return LTTNG_TRACKER_ID_STATUS_INVALID; + } + + *value = id->value; + return LTTNG_TRACKER_ID_STATUS_OK; +} + +bool lttng_tracker_id_is_equal(const struct lttng_tracker_id *left, + const struct lttng_tracker_id *right) +{ + if (left->type != right->type) { + return 0; + } + + switch (left->type) { + case LTTNG_ID_ALL: + return 1; + case LTTNG_ID_VALUE: + if (left->value != right->value) { + return 0; + } + break; + case LTTNG_ID_STRING: + if (strcmp(left->string, right->string) != 0) { + return 0; + } + break; + default: + /* + * Normally this should return true, but comparing unset tracker + * id is "invalid". + */ + return 0; + } + return 1; +} + +struct lttng_tracker_id *lttng_tracker_id_copy( + const struct lttng_tracker_id *orig) +{ + struct lttng_tracker_id *copy = NULL; + enum lttng_tracker_id_status status; + + copy = lttng_tracker_id_create(); + if (copy == NULL) { + goto error; + } + + switch (orig->type) { + case LTTNG_ID_ALL: + status = lttng_tracker_id_set_all(copy); + break; + case LTTNG_ID_VALUE: + status = lttng_tracker_id_set_value(copy, orig->value); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + goto error; + } + break; + case LTTNG_ID_STRING: + status = lttng_tracker_id_set_string(copy, orig->string); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + goto error; + } + break; + default: + status = LTTNG_TRACKER_ID_STATUS_OK; + break; + } + + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + goto error; + } + + return copy; +error: + lttng_tracker_id_destroy(copy); + return NULL; +} + +enum lttng_tracker_id_status lttng_tracker_id_get_string( + const struct lttng_tracker_id *id, const char **value) +{ + assert(id); + if (id->type == LTTNG_ID_UNKNOWN) { + *value = NULL; + return LTTNG_TRACKER_ID_STATUS_UNSET; + } + + if (id->type != LTTNG_ID_STRING) { + *value = NULL; + return LTTNG_TRACKER_ID_STATUS_INVALID; + } + + *value = id->string; + return LTTNG_TRACKER_ID_STATUS_OK; +} diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 085005c39..406de885c 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "filter/filter-ast.h" #include "filter/filter-parser.h" @@ -1606,98 +1607,6 @@ int lttng_disable_channel(struct lttng_handle *handle, const char *name) return lttng_ctl_ask_sessiond(&lsm, NULL); } -static int lttng_track_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - enum lttcomm_sessiond_command cmd) -{ - struct lttcomm_session_msg lsm; - char *var_data = NULL; - size_t var_data_len = 0; - - /* NULL arguments are forbidden. No default values. */ - if (handle == NULL) { - return -LTTNG_ERR_INVALID; - } - - memset(&lsm, 0, sizeof(lsm)); - - lsm.cmd_type = cmd; - lsm.u.id_tracker.tracker_type = tracker_type; - lsm.u.id_tracker.id_type = id->type; - switch (id->type) { - case LTTNG_ID_ALL: - break; - case LTTNG_ID_VALUE: - lsm.u.id_tracker.u.value = id->value; - break; - case LTTNG_ID_STRING: - var_data = id->string; - var_data_len = strlen(var_data) + 1; /* Includes \0. */ - lsm.u.id_tracker.u.var_len = var_data_len; - break; - default: - return -LTTNG_ERR_INVALID; - } - - COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - - lttng_ctl_copy_string(lsm.session.name, handle->session_name, - sizeof(lsm.session.name)); - - return lttng_ctl_ask_sessiond_varlen_no_cmd_header( - &lsm, var_data, var_data_len, NULL); -} - -/* - * Add ID to session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_track_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id) -{ - return lttng_track_untrack_id(handle, tracker_type, id, LTTNG_TRACK_ID); -} - -/* - * Remove ID from session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id) -{ - return lttng_track_untrack_id( - handle, tracker_type, id, LTTNG_UNTRACK_ID); -} - -/* - * Add PID to session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_track_pid(struct lttng_handle *handle, int pid) -{ - struct lttng_tracker_id id; - - id.type = LTTNG_TRACKER_PID; - id.value = pid; - return lttng_track_id(handle, LTTNG_TRACKER_PID, &id); -} - -/* - * 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 lttng_tracker_id id; - - id.type = LTTNG_TRACKER_PID; - id.value = pid; - return lttng_untrack_id(handle, LTTNG_TRACKER_PID, &id); -} - /* * Lists all available tracepoints of domain. * Sets the contents of the events array. @@ -2923,14 +2832,14 @@ end: * * tracker_type is the type of tracker. * ids is set to an allocated array of IDs currently tracked. On - * success, ids and all the strings it contains must be freed by the caller. + * success, ids and contained ids must be freed/destroy by the caller. * nr_ids is set to the number of entries contained by the ids array. * * Returns 0 on success, else a negative LTTng error code. */ int lttng_list_tracker_ids(struct lttng_handle *handle, enum lttng_tracker_type tracker_type, - struct lttng_tracker_id **_ids, + struct lttng_tracker_id ***_ids, size_t *_nr_ids) { int ret, i; @@ -2939,7 +2848,7 @@ int lttng_list_tracker_ids(struct lttng_handle *handle, char *cmd_payload = NULL, *p; size_t cmd_header_len; size_t nr_ids = 0; - struct lttng_tracker_id *ids = NULL; + struct lttng_tracker_id **ids = NULL; if (handle == NULL) { return -LTTNG_ERR_INVALID; @@ -2978,29 +2887,40 @@ int lttng_list_tracker_ids(struct lttng_handle *handle, for (i = 0; i < nr_ids; i++) { struct lttcomm_tracker_id_header *tracker_id; struct lttng_tracker_id *id; + enum lttng_tracker_id_status status; tracker_id = (struct lttcomm_tracker_id_header *) p; p += sizeof(struct lttcomm_tracker_id_header); - id = &ids[i]; + id = lttng_tracker_id_create(); + if (!id) { + ret = -LTTNG_ERR_NOMEM; + goto error; + } - id->type = tracker_id->type; switch (tracker_id->type) { case LTTNG_ID_ALL: + status = lttng_tracker_id_set_all(id); break; case LTTNG_ID_VALUE: id->value = tracker_id->u.value; + status = lttng_tracker_id_set_value( + id, tracker_id->u.value); break; case LTTNG_ID_STRING: - id->string = strdup(p); - if (!id->string) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } + status = lttng_tracker_id_set_string(id, p); p += tracker_id->u.var_data_len; break; default: goto error; } + + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + ret = -LTTNG_ERR_INVALID; + goto error; + } + + /* Assign the new object to the list */ + ids[i] = id; } free(cmd_payload); *_ids = ids; @@ -3008,12 +2928,8 @@ int lttng_list_tracker_ids(struct lttng_handle *handle, return 0; error: - if (ids) { - for (i = 0; i < nr_ids; i++) { - free(ids[i].string); - } - free(ids); - } + lttng_tracker_ids_destroy(ids, nr_ids); + free(ids); free(cmd_payload); free(cmd_header); return ret; @@ -3032,16 +2948,17 @@ error: int lttng_list_tracker_pids(struct lttng_handle *handle, int *_enabled, int32_t **_pids, size_t *_nr_pids) { - struct lttng_tracker_id *ids = NULL; + struct lttng_tracker_id **ids = NULL; size_t nr_ids = 0; int *pids = NULL; int ret = 0, i; + enum lttng_tracker_id_status status; ret = lttng_list_tracker_ids(handle, LTTNG_TRACKER_PID, &ids, &nr_ids); if (ret < 0) return ret; - if (nr_ids == 1 && ids[0].type == LTTNG_ID_ALL) { + if (nr_ids == 1 && lttng_tracker_id_get_type(ids[0]) == LTTNG_ID_ALL) { *_enabled = 0; goto end; } @@ -3053,20 +2970,18 @@ int lttng_list_tracker_pids(struct lttng_handle *handle, goto end; } for (i = 0; i < nr_ids; i++) { - struct lttng_tracker_id *id = &ids[i]; + struct lttng_tracker_id *id = ids[i]; - if (id->type != LTTNG_ID_VALUE) { + status = lttng_tracker_id_get_value(id, &pids[i]); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { ret = -LTTNG_ERR_UNK; goto end; } - pids[i] = id->value; } *_pids = pids; *_nr_pids = nr_ids; end: - for (i = 0; i < nr_ids; i++) { - free(ids[i].string); - } + lttng_tracker_ids_destroy(ids, nr_ids); free(ids); if (ret < 0) { free(pids); @@ -3208,6 +3123,131 @@ end: return ret; } +static int lttng_track_untrack_id(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + const struct lttng_tracker_id *id, + enum lttcomm_sessiond_command cmd) +{ + int ret; + struct lttcomm_session_msg lsm; + const char *var_data; + size_t var_data_len = 0; + int value; + enum lttng_tracker_id_status status; + + /* NULL arguments are forbidden. No default values. */ + if (handle == NULL) { + goto error; + } + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = cmd; + lsm.u.id_tracker.tracker_type = tracker_type; + lsm.u.id_tracker.id_type = lttng_tracker_id_get_type(id); + switch (lsm.u.id_tracker.id_type) { + case LTTNG_ID_ALL: + break; + case LTTNG_ID_VALUE: + status = lttng_tracker_id_get_value(id, &value); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + goto error; + } + lsm.u.id_tracker.u.value = value; + break; + case LTTNG_ID_STRING: + status = lttng_tracker_id_get_string(id, &var_data); + if (status != LTTNG_TRACKER_ID_STATUS_OK) { + goto error; + } + var_data_len = strlen(var_data) + 1; /* Includes \0. */ + lsm.u.id_tracker.u.var_len = var_data_len; + break; + default: + goto error; + } + + COPY_DOMAIN_PACKED(lsm.domain, handle->domain); + + lttng_ctl_copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + + ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( + &lsm, (char *) var_data, var_data_len, NULL); + return ret; +error: + return -LTTNG_ERR_INVALID; +} + +/* + * Add ID to session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_track_id(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + const struct lttng_tracker_id *id) +{ + return lttng_track_untrack_id(handle, tracker_type, id, LTTNG_TRACK_ID); +} + +/* + * Remove ID from session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_untrack_id(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + const struct lttng_tracker_id *id) +{ + return lttng_track_untrack_id( + handle, tracker_type, id, LTTNG_UNTRACK_ID); +} + +/* + * Add PID to session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_track_pid(struct lttng_handle *handle, int pid) +{ + int ret; + struct lttng_tracker_id *id = NULL; + enum lttng_tracker_id_status status; + + id = lttng_tracker_id_create(); + status = lttng_tracker_id_set_value(id, pid); + if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { + ret = -LTTNG_ERR_INVALID; + goto error; + } + + ret = lttng_track_id(handle, LTTNG_TRACKER_PID, id); +error: + lttng_tracker_id_destroy(id); + return ret; +} + +/* + * 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) +{ + int ret; + struct lttng_tracker_id *id = NULL; + enum lttng_tracker_id_status status; + + id = lttng_tracker_id_create(); + status = lttng_tracker_id_set_value(id, pid); + if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { + ret = -LTTNG_ERR_INVALID; + goto error; + } + + ret = lttng_untrack_id(handle, LTTNG_TRACKER_PID, id); +error: + lttng_tracker_id_destroy(id); + return ret; +} + /* * lib constructor. */