Issue observed
==============
Address sanitizer reports the following invalid accesses while running
the test_mi test.
❯ ASAN_OPTIONS=detect_odr_violation=0 lttng-sessiond
=================================================================
==289173==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400000e280 at pc 0x55cbbe35e2e0 bp 0x7f01672f1550 sp 0x7f01672f1540
WRITE of size 4 at 0x60400000e280 thread T13
#0 0x55cbbe35e2df in mark_thread_as_ready /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/manage-consumer.cpp:32
#1 0x55cbbe360160 in thread_consumer_management /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/manage-consumer.cpp:267
#2 0x55cbbe336ac4 in launch_thread /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/thread.cpp:66
#3 0x7f01729c15c1 in start_thread (/usr/lib/libc.so.6+0x8d5c1)
#4 0x7f0172a46583 in __clone (/usr/lib/libc.so.6+0x112583)
0x60400000e280 is located 8 bytes to the right of 40-byte region [0x60400000e250,0x60400000e278)
allocated by thread T7 here:
#0 0x7f01733b1fb9 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
#1 0x55cbbe33adf3 in zmalloc_internal ../../../src/common/macros.hpp:60
#2 0x55cbbe33ae03 in thread_notifiers* zmalloc<thread_notifiers>() ../../../src/common/macros.hpp:89
#3 0x55cbbe3617f9 in launch_consumer_management_thread(consumer_data*) /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/manage-consumer.cpp:440
#4 0x55cbbe33cf49 in spawn_consumer_thread /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:188
#5 0x55cbbe33f7cf in start_consumerd /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:394
#6 0x55cbbe345713 in process_client_msg /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:1277
#7 0x55cbbe34d74b in thread_manage_clients /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:2622
#8 0x55cbbe336ac4 in launch_thread /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/thread.cpp:66
#9 0x7f01729c15c1 in start_thread (/usr/lib/libc.so.6+0x8d5c1)
Thread T13 created by T7 here:
#0 0x7f0173353eb7 in __interceptor_pthread_create /usr/src/debug/gcc/libsanitizer/asan/asan_interceptors.cpp:216
#1 0x55cbbe336f9e in lttng_thread_create(char const*, void* (*)(void*), bool (*)(void*), void (*)(void*), void*) /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/thread.cpp:106
#2 0x55cbbe3618cc in launch_consumer_management_thread(consumer_data*) /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/manage-consumer.cpp:453
#3 0x55cbbe33cf49 in spawn_consumer_thread /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:188
#4 0x55cbbe33f7cf in start_consumerd /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:394
#5 0x55cbbe345713 in process_client_msg /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:1277
#6 0x55cbbe34d74b in thread_manage_clients /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:2622
#7 0x55cbbe336ac4 in launch_thread /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/thread.cpp:66
#8 0x7f01729c15c1 in start_thread (/usr/lib/libc.so.6+0x8d5c1)
Thread T7 created by T0 here:
#0 0x7f0173353eb7 in __interceptor_pthread_create /usr/src/debug/gcc/libsanitizer/asan/asan_interceptors.cpp:216
#1 0x55cbbe336f9e in lttng_thread_create(char const*, void* (*)(void*), bool (*)(void*), void (*)(void*), void*) /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/thread.cpp:106
#2 0x55cbbe34eebf in launch_client_thread() /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/client.cpp:2756
#3 0x55cbbe27f31a in main /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/main.cpp:1838
#4 0x7f017296130f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/jgalar/EfficiOS/src/lttng-tools/src/bin/lttng-sessiond/manage-consumer.cpp:32 in mark_thread_as_ready
Shadow bytes around the buggy address:
0x0c087fff9c00: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c087fff9c10: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c087fff9c20: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c087fff9c30: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c087fff9c40: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
=>0x0c087fff9c50:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff9c60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff9c70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff9c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff9c90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c087fff9ca0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==289173==ABORTING
Cause
=====
The start functions of the various worker threads of the session daemon
are implemented in separate translation units (TU). To make use of the
lttng_thread API, they all define different control structures to
control their shutdown.
Those structures are all named 'thread_notifiers' and are all allocated
using zmalloc<>. The various instances of zmalloc<thread_notifiers> all
end up having the same mangled name (e.g.
_Z7zmallocI16thread_notifiersEPT_v).
At link time, only one instance of zmalloc<thread_notifiers> is kept.
Since those structures all have different layout/sizes, this is
problematic. However, it is an acceptable behaviour according to the ODR
[1].
I first considered making the various memory allocation functions in
macros.hpp 'static' which results in each TU holding the appropriate
specialization of the various functions. While this works, it doesn't
make us ODR-compliant. To make a long story short, a program defining
multiple types sharing the same name, in the same namespace, is
ill-formed.
Another concern is that marking all templated free-functions as static
will eventually result in code bloat.
Solution
========
All structures defined in TUs (but not in a header) are placed in
unnamed namespaces (also called anonymous namespaces) [2].
This results in separate copies of the templated functions being
generated when specialized using a structure in an anonymous
namespace (e.g. _Z7zmallocIN12_GLOBAL__N_116thread_notifiersEEPT_v).
We could have renamed the various `thread_notifiers` structures to give
them different names. However, I found those are not the only structures
sharing a name in different TUs. For instance, the same problem applies
to `struct lttng_index` (index in a stream, index in a map).
I propose we systematically namespace structures defined in TUs in the
future.
This will also save us trouble if those POD structures eventually become
non-POD: we would experience the same "clashes" if those structures had
constructors, for example.
References
==========
[1] https://en.cppreference.com/w/cpp/language/definition
[2] https://en.cppreference.com/w/cpp/language/namespace
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I867e5a287ad8cf3ada617335bc1a80b800bf0833
64 files changed:
RING_BUFFER_DISCARD = 1, /* Discard when buffer full */
};
RING_BUFFER_DISCARD = 1, /* Discard when buffer full */
};
struct crash_abi_unknown {
uint8_t magic[RB_CRASH_DUMP_ABI_MAGIC_LEN];
uint64_t mmap_length; /* Overall length of crash record */
struct crash_abi_unknown {
uint8_t magic[RB_CRASH_DUMP_ABI_MAGIC_LEN];
uint64_t mmap_length; /* Overall length of crash record */
uint64_t num_subbuf; /* Number of sub-buffers for writer */
uint32_t mode; /* Buffer mode: 0: overwrite, 1: discard */
};
uint64_t num_subbuf; /* Number of sub-buffers for writer */
uint32_t mode; /* Buffer mode: 0: overwrite, 1: discard */
};
/* Variables */
static const char *progname;
/* Variables */
static const char *progname;
struct trace_chunk_registry_ht_key {
lttng_uuid sessiond_uuid;
};
struct trace_chunk_registry_ht_key {
lttng_uuid sessiond_uuid;
};
struct lttng_trace_chunk_registry *trace_chunk_registry;
struct sessiond_trace_chunk_registry *sessiond_trace_chunk_registry;
};
struct lttng_trace_chunk_registry *trace_chunk_registry;
struct sessiond_trace_chunk_registry *sessiond_trace_chunk_registry;
};
static
unsigned long trace_chunk_registry_ht_key_hash(
static
unsigned long trace_chunk_registry_ht_key_hash(
#endif /* ! defined (__linux__) && ! defined (__sun__) */
#endif /* ! defined (__linux__) && ! defined (__sun__) */
struct tcp_keep_alive_support {
/* TCP keep-alive is supported by this platform. */
bool supported;
struct tcp_keep_alive_support {
/* TCP keep-alive is supported by this platform. */
bool supported;
-static struct tcp_keep_alive_config the_config = {.enabled = false,
+struct tcp_keep_alive_config the_config = {.enabled = false,
.idle_time = -1,
.probe_interval = -1,
.max_probe_count = -1,
.abort_threshold = -1};
.idle_time = -1,
.probe_interval = -1,
.max_probe_count = -1,
.abort_threshold = -1};
-static struct tcp_keep_alive_support the_support = {.supported = false,
+struct tcp_keep_alive_support the_support = {.supported = false,
.idle_time_supported = false,
.probe_interval_supported = false,
.max_probe_count_supported = false,
.abort_threshold_supported = false};
.idle_time_supported = false,
.probe_interval_supported = false,
.max_probe_count_supported = false,
.abort_threshold_supported = false};
/*
* Common parser for string to positive int conversion where the value must be
/*
* Common parser for string to positive int conversion where the value must be
#define THREAD_NAME "Action Executor"
#define MAX_QUEUED_WORK_COUNT 8192
#define THREAD_NAME "Action Executor"
#define MAX_QUEUED_WORK_COUNT 8192
+struct action_executor {
+ struct lttng_thread *thread;
+ struct notification_thread_handle *notification_thread_handle;
+ struct {
+ uint64_t pending_count;
+ struct cds_list_head list;
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+ } work;
+ bool should_quit;
+ uint64_t next_work_item_id;
+};
+
+namespace {
/*
* A work item is composed of a dynamic array of sub-items which
* represent a flattened, and augmented, version of a trigger's actions.
/*
* A work item is composed of a dynamic array of sub-items which
* represent a flattened, and augmented, version of a trigger's actions.
* trigger object at the moment of execution, if the trigger is found to be
* unregistered, the execution is skipped.
*/
* trigger object at the moment of execution, if the trigger is found to be
* unregistered, the execution is skipped.
*/
struct action_work_item {
uint64_t id;
struct action_work_item {
uint64_t id;
LTTNG_OPTIONAL(uint64_t) session_id;
} context;
};
LTTNG_OPTIONAL(uint64_t) session_id;
} context;
};
-struct action_executor {
- struct lttng_thread *thread;
- struct notification_thread_handle *notification_thread_handle;
- struct {
- uint64_t pending_count;
- struct cds_list_head list;
- pthread_cond_t cond;
- pthread_mutex_t lock;
- } work;
- bool should_quit;
- uint64_t next_work_item_id;
-};
/*
* Only return non-zero on a fatal error that should shut down the action
/*
* Only return non-zero on a fatal error that should shut down the action
#include "utils.hpp"
#include "thread.hpp"
#include "utils.hpp"
#include "thread.hpp"
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
sem_t ready;
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
sem_t ready;
unsigned int major, minor;
};
unsigned int major, minor;
};
-static int agent_tracing_enabled = -1;
+int agent_tracing_enabled = -1;
/*
* Note that there is not port here. It's set after this URI is parsed so we
* can let the user define a custom one. However, localhost is ALWAYS the
* default listening address.
*/
/*
* Note that there is not port here. It's set after this URI is parsed so we
* can let the user define a custom one. However, localhost is ALWAYS the
* default listening address.
*/
-static const char *default_reg_uri =
- "tcp://" DEFAULT_NETWORK_VIEWER_BIND_ADDRESS;
+const char *default_reg_uri = "tcp://" DEFAULT_NETWORK_VIEWER_BIND_ADDRESS;
+} /* namespace */
/*
* Update agent application using the given socket. This is done just after
/*
* Update agent application using the given socket. This is done just after
/*
* Agent application context representation.
*/
/*
* Agent application context representation.
*/
struct agent_app_ctx {
char *provider_name;
char *ctx_name;
struct agent_app_ctx {
char *provider_name;
char *ctx_name;
/* For call_rcu teardown. */
struct rcu_head rcu_node;
};
/* For call_rcu teardown. */
struct rcu_head rcu_node;
};
/*
* Human readable agent return code.
/*
* Human readable agent return code.
#include "kernel.hpp"
#include "cmd.hpp"
#include "kernel.hpp"
#include "cmd.hpp"
struct cmd_clear_session_reply_context {
int reply_sock_fd;
};
struct cmd_clear_session_reply_context {
int reply_sock_fd;
};
static
void cmd_clear_session_reply(const struct ltt_session *session,
static
void cmd_clear_session_reply(const struct ltt_session *session,
#include "testpoint.hpp"
#include "utils.hpp"
#include "testpoint.hpp"
#include "utils.hpp"
+namespace {
+bool is_root;
-static struct thread_state {
sem_t ready;
bool running;
int client_sock;
} thread_state;
sem_t ready;
bool running;
int client_sock;
} thread_state;
static void set_thread_status(bool running)
{
static void set_thread_status(bool running)
{
/* Sleep for 100ms between each check for the shm path's deletion. */
#define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000
/* Sleep for 100ms between each check for the shm path's deletion. */
#define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000
+static enum lttng_error_code wait_on_path(void *path);
+
+namespace {
struct cmd_destroy_session_reply_context {
int reply_sock_fd;
bool implicit_rotation_on_destroy;
struct cmd_destroy_session_reply_context {
int reply_sock_fd;
bool implicit_rotation_on_destroy;
enum lttng_error_code destruction_status;
};
enum lttng_error_code destruction_status;
};
-static enum lttng_error_code wait_on_path(void *path);
-
/*
* Command completion handler that is used by the destroy command
* when a session that has a non-default shm_path is being destroyed.
*
* See comment in cmd_destroy_session() for the rationale.
*/
/*
* Command completion handler that is used by the destroy command
* when a session that has a non-default shm_path is being destroyed.
*
* See comment in cmd_destroy_session() for the rationale.
*/
-static struct destroy_completion_handler {
+struct destroy_completion_handler {
struct cmd_completion_handler handler;
char shm_path[member_sizeof(struct ltt_session, shm_path)];
} destroy_completion_handler = {
struct cmd_completion_handler handler;
char shm_path[member_sizeof(struct ltt_session, shm_path)];
} destroy_completion_handler = {
-static struct cmd_completion_handler *current_completion_handler;
-
/*
* Used to keep a unique index for each relayd socket created where this value
* is associated with streams on the consumer so it can match the right relayd
* to send to. It must be accessed with the relayd_net_seq_idx_lock
* held.
*/
/*
* Used to keep a unique index for each relayd socket created where this value
* is associated with streams on the consumer so it can match the right relayd
* to send to. It must be accessed with the relayd_net_seq_idx_lock
* held.
*/
-static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER;
-static uint64_t relayd_net_seq_idx;
+pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER;
+uint64_t relayd_net_seq_idx;
+} /* namespace */
+static struct cmd_completion_handler *current_completion_handler;
static int validate_ust_event_name(const char *);
static int cmd_enable_event_internal(struct ltt_session *session,
const struct lttng_domain *domain,
static int validate_ust_event_name(const char *);
static int cmd_enable_event_internal(struct ltt_session *session,
const struct lttng_domain *domain,
#include "lttng-sessiond.hpp"
#include "thread.hpp"
#include "lttng-sessiond.hpp"
#include "thread.hpp"
struct thread_notifiers {
struct ust_cmd_queue *ust_cmd_queue;
int apps_cmd_pipe_write_fd;
int apps_cmd_notify_pipe_write_fd;
int dispatch_thread_exit;
};
struct thread_notifiers {
struct ust_cmd_queue *ust_cmd_queue;
int apps_cmd_pipe_write_fd;
int apps_cmd_notify_pipe_write_fd;
int dispatch_thread_exit;
};
/*
* For each tracing session, update newly registered apps. The session list
/*
* For each tracing session, update newly registered apps. The session list
#define ERROR_COUNTER_INDEX_HT_INITIAL_SIZE 16
#define ERROR_COUNTER_INDEX_HT_INITIAL_SIZE 16
struct index_ht_entry {
struct lttng_ht_node_u64 node;
uint64_t error_counter_index;
struct index_ht_entry {
struct lttng_ht_node_u64 node;
uint64_t error_counter_index;
-static struct kernel_error_accounting_entry kernel_error_accounting_entry;
+struct kernel_error_accounting_entry kernel_error_accounting_entry;
/* Hashtable mapping uid to error_account_entry. */
/* Hashtable mapping uid to error_account_entry. */
-static struct lttng_ht *error_counter_uid_ht;
+struct lttng_ht *error_counter_uid_ht;
struct error_accounting_state {
struct lttng_index_allocator *index_allocator;
struct error_accounting_state {
struct lttng_index_allocator *index_allocator;
uint64_t number_indices;
};
uint64_t number_indices;
};
-static struct error_accounting_state ust_state;
-static struct error_accounting_state kernel_state;
+struct error_accounting_state ust_state;
+struct error_accounting_state kernel_state;
+} /* namespace */
static inline void get_trigger_info_for_log(const struct lttng_trigger *trigger,
const char **trigger_name,
static inline void get_trigger_info_for_log(const struct lttng_trigger *trigger,
const char **trigger_name,
}
#ifdef HAVE_LIBLTTNG_UST_CTL
}
#ifdef HAVE_LIBLTTNG_UST_CTL
struct event_notifier_counter {
pthread_mutex_t lock;
long count;
};
struct event_notifier_counter {
pthread_mutex_t lock;
long count;
};
-static struct event_notifier_counter the_event_notifier_counter;
+struct event_notifier_counter the_event_notifier_counter;
+} /* namespace */
static void free_ust_error_accounting_entry(struct rcu_head *head)
{
static void free_ust_error_accounting_entry(struct rcu_head *head)
{
#include "utils.hpp"
#include "thread.hpp"
#include "utils.hpp"
#include "thread.hpp"
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
sem_t ready;
};
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
sem_t ready;
};
static
void mark_thread_as_ready(struct thread_notifiers *notifiers)
static
void mark_thread_as_ready(struct thread_notifiers *notifiers)
#include "utils.hpp"
#include "thread.hpp"
#include "utils.hpp"
#include "thread.hpp"
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
int apps_cmd_pipe_read_fd;
};
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
int apps_cmd_pipe_read_fd;
};
static void cleanup_application_management_thread(void *data)
{
static void cleanup_application_management_thread(void *data)
{
#include "thread.hpp"
#include "ust-consumer.hpp"
#include "thread.hpp"
#include "ust-consumer.hpp"
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
struct consumer_data *consumer_data;
sem_t ready;
int initialization_result;
};
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
struct consumer_data *consumer_data;
sem_t ready;
int initialization_result;
};
static void mark_thread_as_ready(struct thread_notifiers *notifiers)
{
static void mark_thread_as_ready(struct thread_notifiers *notifiers)
{
#include "kernel.hpp"
#include "kernel-consumer.hpp"
#include "kernel.hpp"
#include "kernel-consumer.hpp"
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
int kernel_poll_pipe_read_fd;
};
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
int kernel_poll_pipe_read_fd;
};
/*
* Update the kernel poll set of all channel fd available over all tracing
/*
* Update the kernel poll set of all channel fd available over all tracing
LTTNG_OBJECT_TYPE_SESSION,
};
LTTNG_OBJECT_TYPE_SESSION,
};
-struct lttng_trigger_list_element {
- /* No ownership of the trigger object is assumed. */
- struct lttng_trigger *trigger;
- struct cds_list_head node;
-};
-
struct lttng_channel_trigger_list {
struct channel_key channel_key;
/* List of struct lttng_trigger_list_element. */
struct lttng_channel_trigger_list {
struct channel_key channel_key;
/* List of struct lttng_trigger_list_element. */
struct rcu_head rcu_node;
};
struct rcu_head rcu_node;
};
+namespace {
+struct lttng_trigger_list_element {
+ /* No ownership of the trigger object is assumed. */
+ struct lttng_trigger *trigger;
+ struct cds_list_head node;
+};
+
struct lttng_trigger_ht_element {
struct lttng_trigger *trigger;
struct cds_lfht_node node;
struct lttng_trigger_ht_element {
struct lttng_trigger *trigger;
struct cds_lfht_node node;
/* call_rcu delayed reclaim. */
struct rcu_head rcu_node;
};
/* call_rcu delayed reclaim. */
struct rcu_head rcu_node;
};
static unsigned long hash_channel_key(struct channel_key *key);
static int evaluate_buffer_condition(const struct lttng_condition *condition,
static unsigned long hash_channel_key(struct channel_key *key);
static int evaluate_buffer_condition(const struct lttng_condition *condition,
#include "utils.hpp"
#include "thread.hpp"
#include "utils.hpp"
#include "thread.hpp"
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
int apps_cmd_notify_pipe_read_fd;
};
struct thread_notifiers {
struct lttng_pipe *quit_pipe;
int apps_cmd_notify_pipe_read_fd;
};
/*
* This thread manage application notify communication.
/*
* This thread manage application notify communication.
#include "utils.hpp"
#include "thread.hpp"
#include "utils.hpp"
#include "thread.hpp"
struct thread_state {
struct lttng_pipe *quit_pipe;
struct ust_cmd_queue *ust_cmd_queue;
struct thread_state {
struct lttng_pipe *quit_pipe;
struct ust_cmd_queue *ust_cmd_queue;
bool running;
int application_socket;
};
bool running;
int application_socket;
};
/*
* Creates the application socket.
/*
* Creates the application socket.
struct lttng_poll_event events;
};
struct lttng_poll_event events;
};
-struct rotation_thread_job {
- enum rotation_thread_job_type type;
- struct ltt_session *session;
- /* List member in struct rotation_thread_timer_queue. */
- struct cds_list_head head;
-};
-
/*
* The timer thread enqueues jobs and wakes up the rotation thread.
* When the rotation thread wakes up, it empties the queue.
/*
* The timer thread enqueues jobs and wakes up the rotation thread.
* When the rotation thread wakes up, it empties the queue.
struct lttng_pipe *quit_pipe;
};
struct lttng_pipe *quit_pipe;
};
+namespace {
+struct rotation_thread_job {
+ enum rotation_thread_job_type type;
+ struct ltt_session *session;
+ /* List member in struct rotation_thread_timer_queue. */
+ struct cds_list_head head;
+};
+} /* namespace */
+
static
const char *get_job_type_str(enum rotation_thread_job_type job_type)
{
static
const char *get_job_type_str(enum rotation_thread_job_type job_type)
{
#include "timer.hpp"
#include "cmd.hpp"
#include "timer.hpp"
#include "cmd.hpp"
struct ltt_session_destroy_notifier_element {
ltt_session_destroy_notifier notifier;
void *user_data;
struct ltt_session_destroy_notifier_element {
ltt_session_destroy_notifier notifier;
void *user_data;
* using session_lock() and session_unlock().
*/
* using session_lock() and session_unlock().
*/
+/* These characters are forbidden in a session name. Used by validate_name. */
+const char *forbidden_name_chars = "/";
+
+/* Global hash table to keep the sessions, indexed by id. */
+struct lttng_ht *ltt_sessions_ht_by_id = NULL;
+/* Global hash table to keep the sessions, indexed by name. */
+struct lttng_ht *ltt_sessions_ht_by_name = NULL;
+
/*
* Init tracing session list.
*
* Please see session.h for more explanation and correct usage of the list.
*/
/*
* Init tracing session list.
*
* Please see session.h for more explanation and correct usage of the list.
*/
-static struct ltt_session_list ltt_session_list = {
+struct ltt_session_list the_session_list = {
.lock = PTHREAD_MUTEX_INITIALIZER,
.removal_cond = PTHREAD_COND_INITIALIZER,
.next_uuid = 0,
.lock = PTHREAD_MUTEX_INITIALIZER,
.removal_cond = PTHREAD_COND_INITIALIZER,
.next_uuid = 0,
- .head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
+ .head = CDS_LIST_HEAD_INIT(the_session_list.head),
-
-/* These characters are forbidden in a session name. Used by validate_name. */
-static const char *forbidden_name_chars = "/";
-
-/* Global hash table to keep the sessions, indexed by id. */
-static struct lttng_ht *ltt_sessions_ht_by_id = NULL;
-/* Global hash table to keep the sessions, indexed by name. */
-static struct lttng_ht *ltt_sessions_ht_by_name = NULL;
/*
* Validate the session name for forbidden characters.
/*
* Validate the session name for forbidden characters.
- cds_list_add(&ls->list, <t_session_list.head);
- return ltt_session_list.next_uuid++;
+ cds_list_add(&ls->list, &the_session_list.head);
+ return the_session_list.next_uuid++;
*/
struct ltt_session_list *session_get_list(void)
{
*/
struct ltt_session_list *session_get_list(void)
{
- return <t_session_list;
+ return &the_session_list;
*/
void session_list_wait_empty(void)
{
*/
void session_list_wait_empty(void)
{
- pthread_mutex_lock(<t_session_list.lock);
- while (!cds_list_empty(<t_session_list.head)) {
- pthread_cond_wait(<t_session_list.removal_cond,
- <t_session_list.lock);
+ pthread_mutex_lock(&the_session_list.lock);
+ while (!cds_list_empty(&the_session_list.head)) {
+ pthread_cond_wait(&the_session_list.removal_cond,
+ &the_session_list.lock);
- pthread_mutex_unlock(<t_session_list.lock);
+ pthread_mutex_unlock(&the_session_list.lock);
*/
void session_lock_list(void)
{
*/
void session_lock_list(void)
{
- pthread_mutex_lock(<t_session_list.lock);
+ pthread_mutex_lock(&the_session_list.lock);
*/
int session_trylock_list(void)
{
*/
int session_trylock_list(void)
{
- return pthread_mutex_trylock(<t_session_list.lock);
+ return pthread_mutex_trylock(&the_session_list.lock);
*/
void session_unlock_list(void)
{
*/
void session_unlock_list(void)
{
- pthread_mutex_unlock(<t_session_list.lock);
+ pthread_mutex_unlock(&the_session_list.lock);
pthread_mutex_destroy(&session->lock);
if (session_published) {
pthread_mutex_destroy(&session->lock);
if (session_published) {
- ASSERT_LOCKED(ltt_session_list.lock);
+ ASSERT_LOCKED(the_session_list.lock);
del_session_list(session);
del_session_ht(session);
}
del_session_list(session);
del_session_ht(session);
}
* Broadcast after free-ing to ensure the memory is
* reclaimed before the main thread exits.
*/
* Broadcast after free-ing to ensure the memory is
* reclaimed before the main thread exits.
*/
- ASSERT_LOCKED(ltt_session_list.lock);
- pthread_cond_broadcast(<t_session_list.removal_cond);
+ ASSERT_LOCKED(the_session_list.lock);
+ pthread_cond_broadcast(&the_session_list.removal_cond);
* The session list lock must be held as any session_put()
* may cause the removal of the session from the session_list.
*/
* The session list lock must be held as any session_put()
* may cause the removal of the session from the session_list.
*/
- ASSERT_LOCKED(ltt_session_list.lock);
+ ASSERT_LOCKED(the_session_list.lock);
LTTNG_ASSERT(session->ref.refcount);
urcu_ref_put(&session->ref, session_release);
}
LTTNG_ASSERT(session->ref.refcount);
urcu_ref_put(&session->ref, session_release);
}
struct ltt_session *iter;
LTTNG_ASSERT(name);
struct ltt_session *iter;
LTTNG_ASSERT(name);
- ASSERT_LOCKED(ltt_session_list.lock);
+ ASSERT_LOCKED(the_session_list.lock);
DBG2("Trying to find session by name %s", name);
DBG2("Trying to find session by name %s", name);
- cds_list_for_each_entry(iter, <t_session_list.head, list) {
+ cds_list_for_each_entry(iter, &the_session_list.head, list) {
if (!strncmp(iter->name, name, NAME_MAX) &&
!iter->destroyed) {
goto found;
if (!strncmp(iter->name, name, NAME_MAX) &&
!iter->destroyed) {
goto found;
struct ltt_session *ls;
ASSERT_RCU_READ_LOCKED();
struct ltt_session *ls;
ASSERT_RCU_READ_LOCKED();
- ASSERT_LOCKED(ltt_session_list.lock);
+ ASSERT_LOCKED(the_session_list.lock);
if (!ltt_sessions_ht_by_id) {
goto end;
if (!ltt_sessions_ht_by_id) {
goto end;
enum lttng_error_code ret_code;
struct ltt_session *new_session = NULL;
enum lttng_error_code ret_code;
struct ltt_session *new_session = NULL;
- ASSERT_LOCKED(ltt_session_list.lock);
+ ASSERT_LOCKED(the_session_list.lock);
if (name) {
struct ltt_session *clashing_session;
if (name) {
struct ltt_session *clashing_session;
- ASSERT_LOCKED(ltt_session_list.lock);
+ ASSERT_LOCKED(the_session_list.lock);
ASSERT_LOCKED(session->lock);
session->rotation_state = result;
ASSERT_LOCKED(session->lock);
session->rotation_state = result;
#include <common/error.hpp>
#include <common/defaults.hpp>
#include <common/error.hpp>
#include <common/defaults.hpp>
-static struct thread_list {
+namespace {
+struct thread_list {
struct cds_list_head head;
pthread_mutex_t lock;
} thread_list = {
.head = CDS_LIST_HEAD_INIT(thread_list.head),
.lock = PTHREAD_MUTEX_INITIALIZER,
};
struct cds_list_head head;
pthread_mutex_t lock;
} thread_list = {
.head = CDS_LIST_HEAD_INIT(thread_list.head),
.lock = PTHREAD_MUTEX_INITIALIZER,
};
struct lttng_thread {
struct urcu_ref ref;
struct lttng_thread {
struct urcu_ref ref;
})
#define PTR_TO_UINT(ptr) ((uintptr_t) ptr)
})
#define PTR_TO_UINT(ptr) ((uintptr_t) ptr)
/*
* Handle timer teardown race wrt memory free of private data by sessiond
* signals are handled by a single thread, which permits a synchronization
* point between handling of each signal. Internal lock ensures mutual
* exclusion.
*/
/*
* Handle timer teardown race wrt memory free of private data by sessiond
* signals are handled by a single thread, which permits a synchronization
* point between handling of each signal. Internal lock ensures mutual
* exclusion.
*/
struct timer_signal_data {
/* Thread managing signals. */
pthread_t tid;
struct timer_signal_data {
/* Thread managing signals. */
pthread_t tid;
.qs_done = 0,
.lock = PTHREAD_MUTEX_INITIALIZER,
};
.qs_done = 0,
.lock = PTHREAD_MUTEX_INITIALIZER,
};
/*
* Set custom signal mask to current thread.
/*
* Set custom signal mask to current thread.
#include <common/tracker.hpp>
#include <lttng/lttng-error.h>
#include <common/tracker.hpp>
#include <lttng/lttng-error.h>
+struct process_attr_tracker {
+ enum lttng_tracking_policy policy;
+ struct cds_lfht *inclusion_set_ht;
+};
+
+namespace {
struct process_attr_tracker_value_node {
struct process_attr_value *value;
struct cds_lfht_node inclusion_set_ht_node;
struct rcu_head rcu_head;
};
struct process_attr_tracker_value_node {
struct process_attr_value *value;
struct cds_lfht_node inclusion_set_ht_node;
struct rcu_head rcu_head;
};
-
-struct process_attr_tracker {
- enum lttng_tracking_policy policy;
- struct cds_lfht *inclusion_set_ht;
-};
static void process_attr_tracker_value_node_rcu_free(struct rcu_head *rcu_head)
{
static void process_attr_tracker_value_node_rcu_free(struct rcu_head *rcu_head)
{
#define NR_CLOCK_OFFSET_SAMPLES 10
#define NR_CLOCK_OFFSET_SAMPLES 10
- int64_t offset; /* correlation offset */
- uint64_t measure_delta; /* lower is better */
+ /* correlation offset */
+ int64_t offset;
+ /* lower is better */
+ uint64_t measure_delta;
static
int _lttng_field_statedump(struct ust_registry_session *session,
static
int _lttng_field_statedump(struct ust_registry_session *session,
_PERF_HW_CACHE(optstr "-prefetch-misses", name, type, \
PREFETCH, MISS, hide)
_PERF_HW_CACHE(optstr "-prefetch-misses", name, type, \
PREFETCH, MISS, hide)
const struct ctx_opts {
/* Needed for end-of-list item. */
ctx_opts()
const struct ctx_opts {
/* Needed for end-of-list item. */
ctx_opts()
} ctx_type_list = {
.head = CDS_LIST_HEAD_INIT(ctx_type_list.head),
};
} ctx_type_list = {
.head = CDS_LIST_HEAD_INIT(ctx_type_list.head),
};
/*
* Find context numerical value from string.
/*
* Find context numerical value from string.
lttng_event_expr_destroy((lttng_event_expr *) ptr);
}
lttng_event_expr_destroy((lttng_event_expr *) ptr);
}
struct parse_event_rule_res {
/* Owned by this. */
struct lttng_event_rule *er;
struct parse_event_rule_res {
/* Owned by this. */
struct lttng_event_rule *er;
/* Array of `struct lttng_event_expr *` */
struct lttng_dynamic_pointer_array capture_descriptors;
};
/* Array of `struct lttng_event_expr *` */
struct lttng_dynamic_pointer_array capture_descriptors;
};
static
struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv,
static
struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv,
struct condition_descr {
const char *name;
struct lttng_condition *(*handler) (int *argc, const char ***argv,
int argc_offset);
};
struct condition_descr {
const char *name;
struct lttng_condition *(*handler) (int *argc, const char ***argv,
int argc_offset);
};
static const
struct condition_descr condition_descrs[] = {
static const
struct condition_descr condition_descrs[] = {
struct action_descr {
const char *name;
struct lttng_action *(*handler) (int *argc, const char ***argv,
int argc_offset);
};
struct action_descr {
const char *name;
struct lttng_action *(*handler) (int *argc, const char ***argv,
int argc_offset);
};
static const
struct action_descr action_descrs[] = {
static const
struct action_descr action_descrs[] = {
#include "../command.hpp"
#include "../command.hpp"
struct process_attr_command_args {
enum lttng_process_attr process_attr;
/* Present in the user's command. */
struct process_attr_command_args {
enum lttng_process_attr process_attr;
/* Present in the user's command. */
bool all;
struct lttng_dynamic_pointer_array string_args;
};
bool all;
struct lttng_dynamic_pointer_array string_args;
};
enum cmd_type {
CMD_TRACK,
enum cmd_type {
CMD_TRACK,
#include <strings.h>
#include <ctype.h>
#include <strings.h>
#include <ctype.h>
struct loglevel_name_value {
const char *name;
int value;
};
struct loglevel_name_value {
const char *name;
int value;
};
static
const struct loglevel_name_value loglevel_values[] = {
static
const struct loglevel_name_value loglevel_values[] = {
#define IS_LIST_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_LIST)
#define IS_LIST_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_LIST)
struct lttng_action_list {
struct lttng_action parent;
struct lttng_action_list {
struct lttng_action parent;
*/
char data[];
} LTTNG_PACKED;
*/
char data[];
} LTTNG_PACKED;
static void destroy_lttng_action_list_element(void *ptr)
{
static void destroy_lttng_action_list_element(void *ptr)
{
#include <lttng/action/path-internal.hpp>
#include <lttng/action/path-internal.hpp>
struct lttng_action_path_comm {
uint32_t index_count;
uint64_t indexes[];
} LTTNG_PACKED;
struct lttng_action_path_comm {
uint32_t index_count;
uint64_t indexes[];
} LTTNG_PACKED;
struct lttng_action_path *lttng_action_path_create(
const uint64_t *indexes, size_t index_count)
struct lttng_action_path *lttng_action_path_create(
const uint64_t *indexes, size_t index_count)
rate_policy_mi_serialize_cb mi_serialize;
};
rate_policy_mi_serialize_cb mi_serialize;
};
struct lttng_rate_policy_every_n {
struct lttng_rate_policy parent;
uint64_t interval;
struct lttng_rate_policy_every_n {
struct lttng_rate_policy parent;
uint64_t interval;
struct lttng_rate_policy_every_n_comm {
uint64_t interval;
} LTTNG_PACKED;
struct lttng_rate_policy_every_n_comm {
uint64_t interval;
} LTTNG_PACKED;
/* Forward declaration. */
static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
/* Forward declaration. */
static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
#define IS_ROTATE_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_ROTATE_SESSION)
#define IS_ROTATE_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_ROTATE_SESSION)
struct lttng_action_rotate_session {
struct lttng_action parent;
struct lttng_action_rotate_session {
struct lttng_action parent;
*/
char data[];
} LTTNG_PACKED;
*/
char data[];
} LTTNG_PACKED;
static const struct lttng_rate_policy *
lttng_action_rotate_session_internal_get_rate_policy(
static const struct lttng_rate_policy *
lttng_action_rotate_session_internal_get_rate_policy(
#define IS_SNAPSHOT_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_SNAPSHOT_SESSION)
#define IS_SNAPSHOT_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_SNAPSHOT_SESSION)
struct lttng_action_snapshot_session {
struct lttng_action parent;
struct lttng_action_snapshot_session {
struct lttng_action parent;
*/
char data[];
} LTTNG_PACKED;
*/
char data[];
} LTTNG_PACKED;
static const struct lttng_rate_policy *
lttng_action_snapshot_session_internal_get_rate_policy(
static const struct lttng_rate_policy *
lttng_action_snapshot_session_internal_get_rate_policy(
#define IS_START_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_START_SESSION)
#define IS_START_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_START_SESSION)
struct lttng_action_start_session {
struct lttng_action parent;
struct lttng_action_start_session {
struct lttng_action parent;
*/
char data[];
} LTTNG_PACKED;
*/
char data[];
} LTTNG_PACKED;
static const struct lttng_rate_policy *
lttng_action_start_session_internal_get_rate_policy(
static const struct lttng_rate_policy *
lttng_action_start_session_internal_get_rate_policy(
#define IS_STOP_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_STOP_SESSION)
#define IS_STOP_SESSION_ACTION(action) \
(lttng_action_get_type(action) == LTTNG_ACTION_TYPE_STOP_SESSION)
struct lttng_action_stop_session {
struct lttng_action parent;
struct lttng_action_stop_session {
struct lttng_action parent;
*/
char data[];
} LTTNG_PACKED;
*/
char data[];
} LTTNG_PACKED;
static const struct lttng_rate_policy *
lttng_action_stop_session_internal_get_rate_policy(
static const struct lttng_rate_policy *
lttng_action_stop_session_internal_get_rate_policy(
struct rmdir_frame {
ssize_t parent_frame_idx;
DIR *dir;
struct rmdir_frame {
ssize_t parent_frame_idx;
DIR *dir;
/* Size including '\0'. */
size_t path_size;
};
/* Size including '\0'. */
size_t path_size;
};
static
void rmdir_frame_fini(void *data)
static
void rmdir_frame_fini(void *data)
#define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7
#define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7
struct session_config_validation_ctx {
xmlSchemaParserCtxtPtr parser_ctx;
xmlSchemaPtr schema;
xmlSchemaValidCtxtPtr schema_validation_ctx;
};
struct session_config_validation_ctx {
xmlSchemaParserCtxtPtr parser_ctx;
xmlSchemaPtr schema;
xmlSchemaValidCtxtPtr schema_validation_ctx;
};
const char * const config_element_all = "all";
LTTNG_EXPORT const char *config_xml_encoding = "UTF-8";
const char * const config_element_all = "all";
LTTNG_EXPORT const char *config_xml_encoding = "UTF-8";
struct consumer_output {
int enabled;
char *path;
char *control_uri;
char *data_uri;
};
struct consumer_output {
int enabled;
char *path;
char *control_uri;
char *data_uri;
};
/*
* Returns a xmlChar string which must be released using xmlFree().
/*
* Returns a xmlChar string which must be released using xmlFree().
CONSUMER_CHANNEL_QUIT,
};
CONSUMER_CHANNEL_QUIT,
};
struct consumer_channel_msg {
enum consumer_channel_action action;
struct lttng_consumer_channel *chan; /* add */
uint64_t key; /* del */
};
struct consumer_channel_msg {
enum consumer_channel_action action;
struct lttng_consumer_channel *chan; /* add */
uint64_t key; /* del */
};
+/*
+ * Global hash table containing respectively metadata and data streams. The
+ * stream element in this ht should only be updated by the metadata poll thread
+ * for the metadata and the data poll thread for the data.
+ */
+struct lttng_ht *metadata_ht;
+struct lttng_ht *data_ht;
+} /* namespace */
+
/* Flag used to temporarily pause data consumption from testpoints. */
int data_consumption_paused;
/* Flag used to temporarily pause data consumption from testpoints. */
int data_consumption_paused;
-/*
- * Global hash table containing respectively metadata and data streams. The
- * stream element in this ht should only be updated by the metadata poll thread
- * for the metadata and the data poll thread for the data.
- */
-static struct lttng_ht *metadata_ht;
-static struct lttng_ht *data_ht;
-
static const char *get_consumer_domain(void)
{
switch (the_consumer_data.type) {
static const char *get_consumer_domain(void)
{
switch (the_consumer_data.type) {
enum lttng_error_query_target_type target_type;
};
enum lttng_error_query_target_type target_type;
};
+struct lttng_error_query_result {
+ enum lttng_error_query_result_type type;
+ char *name;
+ char *description;
+};
+
+struct lttng_error_query_results {
+ struct lttng_dynamic_pointer_array results;
+};
+
+namespace {
struct lttng_error_query_comm {
/* enum lttng_error_query_target_type */
int8_t target_type;
struct lttng_error_query_comm {
/* enum lttng_error_query_target_type */
int8_t target_type;
struct lttng_action_path action_path;
};
struct lttng_action_path action_path;
};
-struct lttng_error_query_result {
- enum lttng_error_query_result_type type;
- char *name;
- char *description;
-};
-
struct lttng_error_query_result_comm {
/* enum lttng_error_query_result_type */
uint8_t type;
struct lttng_error_query_result_comm {
/* enum lttng_error_query_result_type */
uint8_t type;
/* `count` instances of `struct lttng_error_query_result` follow. */
char payload[];
} LTTNG_PACKED;
/* `count` instances of `struct lttng_error_query_result` follow. */
char payload[];
} LTTNG_PACKED;
-
-struct lttng_error_query_results {
- struct lttng_dynamic_pointer_array results;
-};
static
enum lttng_error_code lttng_error_query_result_mi_serialize(
static
enum lttng_error_code lttng_error_query_result_mi_serialize(
#include <lttng/lttng-error.h>
#include <lttng/userspace-probe-internal.hpp>
#include <lttng/lttng-error.h>
#include <lttng/userspace-probe-internal.hpp>
struct event_list_element {
struct lttng_event *event;
struct lttng_event_exclusion *exclusions;
char *filter_expression;
};
struct event_list_element {
struct lttng_event *event;
struct lttng_event_exclusion *exclusions;
char *filter_expression;
};
static void event_list_destructor(void *ptr)
{
static void event_list_destructor(void *ptr)
{
struct lttng_unlinked_file_pool *unlinked_file_pool;
};
struct lttng_unlinked_file_pool *unlinked_file_pool;
};
struct open_properties {
int flags;
LTTNG_OPTIONAL(mode_t) mode;
struct open_properties {
int flags;
LTTNG_OPTIONAL(mode_t) mode;
struct rcu_head rcu_head;
};
struct rcu_head rcu_head;
};
pthread_mutex_t lock;
bool initialized;
unsigned long value;
pthread_mutex_t lock;
bool initialized;
unsigned long value;
.initialized = false,
.value = 0,
};
.initialized = false,
.value = 0,
};
static int match_fd(struct cds_lfht_node *node, const void *key);
static void unsuspendable_fd_destroy(struct unsuspendable_fd *entry);
static int match_fd(struct cds_lfht_node *node, const void *key);
static void unsuspendable_fd_destroy(struct unsuspendable_fd *entry);
struct inode_id {
dev_t device;
ino_t inode;
};
struct inode_id {
dev_t device;
ino_t inode;
};
struct lttng_inode_registry {
/* Hashtable of inode_id to lttng_inode. */
struct lttng_inode_registry {
/* Hashtable of inode_id to lttng_inode. */
pthread_mutex_t lock;
bool initialized;
unsigned long value;
pthread_mutex_t lock;
bool initialized;
unsigned long value;
.initialized = false,
.value = 0,
};
.initialized = false,
.value = 0,
};
static unsigned long lttng_inode_id_hash(const struct inode_id *id)
{
static unsigned long lttng_inode_id_hash(const struct inode_id *id)
{
struct create_args {
struct lttng_poll_event *events;
int size;
int flags;
};
struct create_args {
struct lttng_poll_event *events;
int size;
int flags;
};
static int open_epoll(void *data, int *out_fd)
{
static int open_epoll(void *data, int *out_fd)
{
tracker, pipe, 2, close_pipe, NULL);
}
tracker, pipe, 2, close_pipe, NULL);
}
struct open_directory_handle_args {
const struct lttng_directory_handle *in_handle;
struct lttng_directory_handle *ret_handle;
const char *path;
};
struct open_directory_handle_args {
const struct lttng_directory_handle *in_handle;
struct lttng_directory_handle *ret_handle;
const char *path;
};
static
int open_directory_handle(void *_args, int *out_fds)
static
int open_directory_handle(void *_args, int *out_fds)
uint64_t nb_allocated_indexes;
};
uint64_t nb_allocated_indexes;
};
struct lttng_index {
uint64_t index;
struct cds_list_head head;
};
struct lttng_index {
uint64_t index;
struct cds_list_head head;
};
struct lttng_index_allocator *lttng_index_allocator_create(
uint64_t index_count)
struct lttng_index_allocator *lttng_index_allocator_create(
uint64_t index_count)
LTTNG_EXPORT const char *config_str_false = "false";
LTTNG_EXPORT const char *config_str_off = "off";
LTTNG_EXPORT const char *config_str_false = "false";
LTTNG_EXPORT const char *config_str_off = "off";
struct handler_filter_args {
const char* section;
config_entry_handler_cb handler;
void *user_data;
};
struct handler_filter_args {
const char* section;
config_entry_handler_cb handler;
void *user_data;
};
static int config_entry_handler_filter(struct handler_filter_args *args,
const char *section, const char *name, const char *value)
static int config_entry_handler_filter(struct handler_filter_args *args,
const char *section, const char *name, const char *value)
struct lttng_elf_ehdr {
uint16_t e_type;
uint16_t e_machine;
struct lttng_elf_ehdr {
uint16_t e_type;
uint16_t e_machine;
uint64_t st_value;
uint64_t st_size;
};
uint64_t st_value;
uint64_t st_size;
};
struct lttng_elf {
int fd;
struct lttng_elf {
int fd;
#define GETPW_BUFFER_FALLBACK_SIZE 4096
#define GETPW_BUFFER_FALLBACK_SIZE 4096
-struct run_as_data;
-struct run_as_ret;
-typedef int (*run_as_fct)(struct run_as_data *data, struct run_as_ret *ret_value);
-
enum run_as_cmd {
RUN_AS_MKDIR,
RUN_AS_MKDIRAT,
enum run_as_cmd {
RUN_AS_MKDIR,
RUN_AS_MKDIRAT,
RUN_AS_GENERATE_FILTER_BYTECODE,
};
RUN_AS_GENERATE_FILTER_BYTECODE,
};
+namespace {
+struct run_as_data;
+struct run_as_ret;
+typedef int (*run_as_fct)(struct run_as_data *data, struct run_as_ret *ret_value);
+
struct run_as_mkdir_data {
int dirfd;
char path[LTTNG_PATH_MAX];
struct run_as_mkdir_data {
int dirfd;
char path[LTTNG_PATH_MAX];
-static const struct run_as_command_properties command_properties[] = {
+const struct run_as_command_properties command_properties[] = {
{
.in_fds_offset = offsetof(struct run_as_data, u.mkdir.dirfd),
.out_fds_offset = -1,
{
.in_fds_offset = offsetof(struct run_as_data, u.mkdir.dirfd),
.out_fds_offset = -1,
};
/* Single global worker per process (for now). */
};
/* Single global worker per process (for now). */
-static run_as_worker_data *global_worker;
+run_as_worker_data *global_worker;
/* Lock protecting the worker. */
/* Lock protecting the worker. */
-static pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
+} /* namespace */
#include <time.h>
#include <stdio.h>
#include <time.h>
#include <stdio.h>
struct lttng_session_descriptor_network_location {
struct lttng_uri *control;
struct lttng_uri *data;
};
struct lttng_session_descriptor_network_location {
struct lttng_uri *control;
struct lttng_uri *data;
};
struct lttng_session_descriptor {
enum lttng_session_descriptor_type type;
struct lttng_session_descriptor {
enum lttng_session_descriptor_type type;
struct lttng_session_descriptor_snapshot {
struct lttng_session_descriptor base;
/*
struct lttng_session_descriptor_snapshot {
struct lttng_session_descriptor base;
/*
/* Live-specific parameters. */
uint64_t live_timer_us;
} LTTNG_PACKED;
/* Live-specific parameters. */
uint64_t live_timer_us;
} LTTNG_PACKED;
static
struct lttng_uri *uri_copy(const struct lttng_uri *uri)
static
struct lttng_uri *uri_copy(const struct lttng_uri *uri)
/*
* This is essentially the same as `struct lttng_snapshot_output`, but packed.
*/
/*
* This is essentially the same as `struct lttng_snapshot_output`, but packed.
*/
char ctrl_url[PATH_MAX];
char data_url[PATH_MAX];
} LTTNG_PACKED;
char ctrl_url[PATH_MAX];
char data_url[PATH_MAX];
} LTTNG_PACKED;
int lttng_snapshot_output_serialize(
const struct lttng_snapshot_output *output,
int lttng_snapshot_output_serialize(
const struct lttng_snapshot_output *output,
#include "macros.hpp"
#include "spawn-viewer.hpp"
#include "macros.hpp"
#include "spawn-viewer.hpp"
-
-static const char *babeltrace_bin = CONFIG_BABELTRACE_BIN;
-static const char *babeltrace2_bin = CONFIG_BABELTRACE2_BIN;
-
-/*
- * This is needed for each viewer since we are using execvp().
- */
-static const char *babeltrace_opts[] = { "babeltrace" };
-static const char *babeltrace2_opts[] = { "babeltrace2" };
-
/*
* Type is also use as the index in the viewers array. So please, make sure
* your enum value is in the right order in the array below.
/*
* Type is also use as the index in the viewers array. So please, make sure
* your enum value is in the right order in the array below.
VIEWER_USER_DEFINED = 2,
};
VIEWER_USER_DEFINED = 2,
};
-static const struct viewer {
+namespace {
+const char *babeltrace_bin = CONFIG_BABELTRACE_BIN;
+const char *babeltrace2_bin = CONFIG_BABELTRACE2_BIN;
+
+/*
+ * This is needed for each viewer since we are using execvp().
+ */
+const char *babeltrace_opts[] = { "babeltrace" };
+const char *babeltrace2_opts[] = { "babeltrace2" };
+
+const struct viewer {
const char *exec_name;
enum viewer_type type;
} viewers[] = {
const char *exec_name;
enum viewer_type type;
} viewers[] = {
{ "babeltrace2", VIEWER_BABELTRACE2 },
{ NULL, VIEWER_USER_DEFINED },
};
{ "babeltrace2", VIEWER_BABELTRACE2 },
{ NULL, VIEWER_USER_DEFINED },
};
static const struct viewer *parse_viewer_option(const char *opt_viewer)
{
static const struct viewer *parse_viewer_option(const char *opt_viewer)
{
enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
struct lttng_trace_chunk *chunk, const char *path);
enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
struct lttng_trace_chunk *chunk, const char *path);
struct chunk_credentials {
bool use_current_user;
struct lttng_credentials user;
};
struct chunk_credentials {
bool use_current_user;
struct lttng_credentials user;
};
/*
* NOTE: Make sure to update:
/*
* NOTE: Make sure to update:
struct fd_tracker *fd_tracker;
};
struct fd_tracker *fd_tracker;
};
/* A trace chunk is uniquely identified by its (session id, chunk id) tuple. */
struct lttng_trace_chunk_registry_element {
struct lttng_trace_chunk chunk;
/* A trace chunk is uniquely identified by its (session id, chunk id) tuple. */
struct lttng_trace_chunk_registry_element {
struct lttng_trace_chunk chunk;
/* call_rcu delayed reclaim. */
struct rcu_head rcu_node;
};
/* call_rcu delayed reclaim. */
struct rcu_head rcu_node;
};
struct lttng_trace_chunk_registry {
struct cds_lfht *ht;
};
struct lttng_trace_chunk_registry {
struct cds_lfht *ht;
};
struct fs_handle_untracked {
struct fs_handle parent;
int fd;
struct fs_handle_untracked {
struct fs_handle parent;
int fd;
char *path;
} location;
};
char *path;
} location;
};
static
int fs_handle_untracked_get_fd(struct fs_handle *handle);
static
int fs_handle_untracked_get_fd(struct fs_handle *handle);
struct process_attr_tracker_values_comm_header {
uint32_t count;
} LTTNG_PACKED;
struct process_attr_tracker_values_comm_header {
uint32_t count;
} LTTNG_PACKED;
uint32_t name_len;
} value;
} LTTNG_PACKED;
uint32_t name_len;
} value;
} LTTNG_PACKED;
#define GET_INTEGRAL_COMM_VALUE(value_ptr, as_type) \
((as_type)(std::is_signed<as_type>::value ? (value_ptr)->u._signed : \
#define GET_INTEGRAL_COMM_VALUE(value_ptr, as_type) \
((as_type)(std::is_signed<as_type>::value ? (value_ptr)->u._signed : \
P_NET, P_NET6, P_FILE, P_TCP, P_TCP6,
};
P_NET, P_NET6, P_FILE, P_TCP, P_TCP6,
};
struct uri_proto {
const char *name;
const char *leading_string;
struct uri_proto {
const char *name;
const char *leading_string;
};
/* Supported protocols */
};
/* Supported protocols */
-static const struct uri_proto proto_uri[] = {
+const struct uri_proto proto_uri[] = {
{ .name = "file", .leading_string = "file://", .code = P_FILE, .type = LTTNG_PROTO_TYPE_NONE, .dtype = LTTNG_DST_PATH },
{ .name = "net", .leading_string = "net://", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 },
{ .name = "net4", .leading_string = "net4://", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 },
{ .name = "file", .leading_string = "file://", .code = P_FILE, .type = LTTNG_PROTO_TYPE_NONE, .dtype = LTTNG_DST_PATH },
{ .name = "net", .leading_string = "net://", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 },
{ .name = "net4", .leading_string = "net4://", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 },
/* Invalid proto marking the end of the array. */
{}
};
/* Invalid proto marking the end of the array. */
{}
};
/*
* Return pointer to the character in s matching one of the characters in
/*
* Return pointer to the character in s matching one of the characters in
typedef void (*test_case_cb)(FILE *output_file);
typedef void (*test_case_cb)(FILE *output_file);
-static const struct test_case {
+namespace {
+const struct test_case {
test_case_cb run;
bool produces_validation_info;
int timeout;
test_case_cb run;
bool produces_validation_info;
int timeout;
struct pollfd *ufds;
int value;
};
struct pollfd *ufds;
int value;
};
static
void test_select_big(void)
static
void test_select_big(void)
LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
#endif
LTTNG_EXPORT DEFINE_LTTNG_UST_SIGBUS_STATE();
#endif
-static int control_sock;
struct live_session *session;
struct live_session *session;
-static int first_packet_offset;
-static int first_packet_len;
-static int first_packet_stream_id = -1;
+int first_packet_offset;
+int first_packet_len;
+int first_packet_stream_id = -1;
struct viewer_stream {
uint64_t id;
struct viewer_stream {
uint64_t id;
uint64_t live_timer_interval;
uint64_t stream_count;
};
uint64_t live_timer_interval;
uint64_t stream_count;
};
static
ssize_t lttng_live_recv(int fd, void *buf, size_t len)
static
ssize_t lttng_live_recv(int fd, void *buf, size_t len)
FIELD_TYPE_ARRAY_FIELD,
};
FIELD_TYPE_ARRAY_FIELD,
};
struct capture_base_field_tuple {
const char *field_name;
enum field_type field_type;
struct capture_base_field_tuple {
const char *field_name;
enum field_type field_type;
validate_cb validate_ust;
validate_cb validate_kernel;
};
validate_cb validate_ust;
validate_cb validate_kernel;
};
static
const char *field_value_type_to_str(enum lttng_event_field_value_type type)
static
const char *field_value_type_to_str(enum lttng_event_field_value_type type)
#include <string.h>
#include <lttng/constant.h>
#include <string.h>
#include <lttng/constant.h>
struct state {
int section_1;
int section_2;
struct state {
int section_1;
int section_2;
int text_entry;
int int_entry;
};
int text_entry;
int int_entry;
};
int lttng_opt_quiet = 1;
int lttng_opt_verbose = 0;
int lttng_opt_quiet = 1;
int lttng_opt_verbose = 0;
struct tracepoint_test {
enum lttng_domain_type type;
bool support_name_pattern_exclusion;
};
struct tracepoint_test {
enum lttng_domain_type type;
bool support_name_pattern_exclusion;
};
typedef const char *(*log_level_name_getter)(int log_level);
typedef const char *(*log_level_name_getter)(int log_level);
/* Number of TAP tests in this file */
#define NUM_TESTS_PER_TEST 1
/* Number of TAP tests in this file */
#define NUM_TESTS_PER_TEST 1
struct test {
const char *stream_path;
const char *session_name;
struct test {
const char *stream_path;
const char *session_name;
const char *leftover;
bool is_valid;
};
const char *leftover;
bool is_valid;
};
int lttng_opt_quiet;
int lttng_opt_mi;
int lttng_opt_quiet;
int lttng_opt_mi;
int lttng_opt_verbose = 3;
int lttng_opt_mi;
int lttng_opt_verbose = 3;
int lttng_opt_mi;
struct valid_test_input {
const char *input;
const char *relative_part;
struct valid_test_input {
const char *input;
const char *relative_part;
};
/* Valid test cases */
};
/* Valid test cases */
-static struct valid_test_input valid_tests_inputs[] = {
+struct valid_test_input valid_tests_inputs[] = {
{ "/a/b/c/d/e", "", "/a/b/c/d/e" },
{ "/a//b//c/d/e", "", "/a/b/c/d/e" },
{ "./a/b/c/d/e", ".", "/a/b/c/d/e" },
{ "/a/b/c/d/e", "", "/a/b/c/d/e" },
{ "/a//b//c/d/e", "", "/a/b/c/d/e" },
{ "./a/b/c/d/e", ".", "/a/b/c/d/e" },
{ "/a/..", "", "/" },
};
char **valid_tests_expected_results;
{ "/a/..", "", "/" },
};
char **valid_tests_expected_results;
-static const int num_valid_tests =
+const int num_valid_tests =
sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
/* Symlinks test cases */
char tree_origin[] = "/tmp/test_utils_expand_path.XXXXXX";
sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
/* Symlinks test cases */
char tree_origin[] = "/tmp/test_utils_expand_path.XXXXXX";
-static const char * const tree_dirs[] = {
+const char * const tree_dirs[] = {
"a",
"a/b",
"a/b/c",
"a/e",
};
"a",
"a/b",
"a/b/c",
"a/e",
};
-static const int num_tree_dirs =
+const int num_tree_dirs =
sizeof(tree_dirs) / sizeof(tree_dirs[0]);
sizeof(tree_dirs) / sizeof(tree_dirs[0]);
-static struct tree_symlink tree_symlinks[] = {
+struct tree_symlink tree_symlinks[] = {
{ "a/d", "b/c/" },
{ "a/g", "d/" },
{ "a/b/f", "../e/" },
{ "a/d", "b/c/" },
{ "a/g", "d/" },
{ "a/b/f", "../e/" },
{ "a/b/k", "c/g/" },
{ "a/b/c/g", "../../../" },
};
{ "a/b/k", "c/g/" },
{ "a/b/c/g", "../../../" },
};
-static const int num_tree_symlinks =
+const int num_tree_symlinks =
sizeof(tree_symlinks) / sizeof(tree_symlinks[0]);
static struct symlink_test_input symlink_tests_inputs[] = {
sizeof(tree_symlinks) / sizeof(tree_symlinks[0]);
static struct symlink_test_input symlink_tests_inputs[] = {
{ "a/g/../l/../", "a/b/" },
{ "a/b/h/g/", "" },
};
{ "a/g/../l/../", "a/b/" },
{ "a/b/h/g/", "" },
};
-static const int num_symlink_tests =
+const int num_symlink_tests =
sizeof(symlink_tests_inputs) / sizeof(symlink_tests_inputs[0]);
/* Invalid test cases */
sizeof(symlink_tests_inputs) / sizeof(symlink_tests_inputs[0]);
/* Invalid test cases */
-static char *invalid_tests_inputs[] = {
+char *invalid_tests_inputs[] = {
-static const int num_invalid_tests =
+const int num_invalid_tests =
sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
#define PRINT_ERR(fmt, args...) \
fprintf(stderr, "test_utils_expand_path: error: " fmt "\n", ## args)
#define PRINT_ERR(fmt, args...) \
fprintf(stderr, "test_utils_expand_path: error: " fmt "\n", ## args)
int lttng_opt_verbose = 3;
int lttng_opt_mi;
int lttng_opt_verbose = 3;
int lttng_opt_mi;
struct valid_test_input {
const char *input;
uint64_t expected_result;
};
/* Valid test cases */
struct valid_test_input {
const char *input;
uint64_t expected_result;
};
/* Valid test cases */
-static struct valid_test_input valid_tests_inputs[] = {
+struct valid_test_input valid_tests_inputs[] = {
{ "0", 0 },
{ "1234", 1234 },
{ "0x400", 1024 },
{ "0", 0 },
{ "1234", 1234 },
{ "0x400", 1024 },
{ "0XA0M", 167772160 },
{ "0xA0G", 171798691840ULL },
};
{ "0XA0M", 167772160 },
{ "0xA0G", 171798691840ULL },
};
-static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
+const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
-static const char *invalid_tests_inputs[] = {
+const char *invalid_tests_inputs[] = {
-static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+} /* namespace */
static void test_utils_parse_size_suffix(void)
{
static void test_utils_parse_size_suffix(void)
{
int lttng_opt_verbose = 3;
int lttng_opt_mi;
int lttng_opt_verbose = 3;
int lttng_opt_mi;
struct valid_test_input {
const char *input;
uint64_t expected_result;
};
/* Valid test cases */
struct valid_test_input {
const char *input;
uint64_t expected_result;
};
/* Valid test cases */
-static struct valid_test_input valid_tests_inputs[] = {
+struct valid_test_input valid_tests_inputs[] = {
{ "0", 0 },
{ "1234", 1234 },
{ "1234us", 1234 },
{ "0", 0 },
{ "1234", 1234 },
{ "1234us", 1234 },
{ "08", 8 },
{ "0145us", 145 },
};
{ "08", 8 },
{ "0145us", 145 },
};
-static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
+const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
-static const char *invalid_tests_inputs[] = {
+const char *invalid_tests_inputs[] = {
-static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
+} /* namespace */
static void test_utils_parse_time_suffix(void)
{
static void test_utils_parse_time_suffix(void)
{
#include <lttng/lttng-error.h>
#include <common/macros.hpp>
#include <lttng/lttng-error.h>
#include <common/macros.hpp>
struct validation_ctx {
xmlSchemaParserCtxtPtr parser_ctx;
xmlSchemaPtr schema;
xmlSchemaValidCtxtPtr schema_validation_ctx;
};
struct validation_ctx {
xmlSchemaParserCtxtPtr parser_ctx;
xmlSchemaPtr schema;
xmlSchemaValidCtxtPtr schema_validation_ctx;
};
enum command_err_code {
CMD_SUCCESS = 0,
enum command_err_code {
CMD_SUCCESS = 0,