From 14e0a13576200091ccaba54c89692ee21672a700 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 30 Mar 2021 09:54:23 -0400 Subject: [PATCH] New API: lttng_ust_init_thread() for async-signal tracing LTTng-UST uses Global Dynamic model TLS variables rather than IE model because many versions of glibc don't preallocate a pool large enough for TLS variables IE model defined in other shared libraries, and causes issues when using LTTng-UST for Java tracing. Because of this use of Global Dynamic TLS variables, users wishing to trace from signal handlers need to explicitly trigger the lazy allocation of those variables for each thread before using them. This can be triggered by calling lttng_ust_init_thread(). Hide the public symbols for ring buffer and counter clients init/exit. Expose new symbols for init/exit of all ring buffer and counter clients instead. Those new symbols are only used by liblttng-ust-ctl, and are thus in an internal header. Signed-off-by: Mathieu Desnoyers Change-Id: I389be1db96e5ff1e9a116311b8adf8676c9752cb --- include/Makefile.am | 1 + include/lttng/ust-thread.h | 29 +++++++ liblttng-ust-ctl/ustctl.c | 29 +------ liblttng-ust/lttng-rb-clients.h | 10 +++ .../lttng-ring-buffer-client-discard-rt.c | 2 + .../lttng-ring-buffer-client-discard.c | 2 + .../lttng-ring-buffer-client-overwrite-rt.c | 2 + .../lttng-ring-buffer-client-overwrite.c | 2 + liblttng-ust/lttng-ring-buffer-client.h | 4 +- liblttng-ust/lttng-ust-comm.c | 84 +++++++++++++------ liblttng-ust/ust-events-internal.h | 31 +++++++ 11 files changed, 143 insertions(+), 53 deletions(-) create mode 100644 include/lttng/ust-thread.h diff --git a/include/Makefile.am b/include/Makefile.am index 4d4761d9..854b4785 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -32,6 +32,7 @@ nobase_include_HEADERS = \ lttng/ust-clock.h \ lttng/ust-getcpu.h \ lttng/ust-libc-wrapper.h \ + lttng/ust-thread.h \ lttng/urcu/pointer.h \ lttng/urcu/urcu-ust.h \ lttng/urcu/static/pointer.h \ diff --git a/include/lttng/ust-thread.h b/include/lttng/ust-thread.h new file mode 100644 index 00000000..2c84ae76 --- /dev/null +++ b/include/lttng/ust-thread.h @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright (C) 2021 Mathieu Desnoyers + */ + +#ifndef _LTTNG_UST_THREAD_H +#define _LTTNG_UST_THREAD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Initialize this thread's LTTng-UST data structures. There is + * typically no need to call this, because LTTng-UST initializes its + * per-thread data structures lazily, but it should be called explicitly + * upon creation of each thread before signal handlers nesting over + * those threads use LTTng-UST tracepoints. + */ +void lttng_ust_init_thread(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _LTTNG_UST_THREAD_H */ diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c index 40b3667b..9acce7a9 100644 --- a/liblttng-ust-ctl/ustctl.c +++ b/liblttng-ust-ctl/ustctl.c @@ -84,17 +84,6 @@ struct ustctl_daemon_counter { struct ustctl_counter_attr *attr; /* initial attributes */ }; -extern void lttng_ring_buffer_client_overwrite_init(void); -extern void lttng_ring_buffer_client_overwrite_rt_init(void); -extern void lttng_ring_buffer_client_discard_init(void); -extern void lttng_ring_buffer_client_discard_rt_init(void); -extern void lttng_ring_buffer_metadata_client_init(void); -extern void lttng_ring_buffer_client_overwrite_exit(void); -extern void lttng_ring_buffer_client_overwrite_rt_exit(void); -extern void lttng_ring_buffer_client_discard_exit(void); -extern void lttng_ring_buffer_client_discard_rt_exit(void); -extern void lttng_ring_buffer_metadata_client_exit(void); - int ustctl_release_handle(int sock, int handle) { struct ustcomm_ust_msg lum; @@ -2917,24 +2906,14 @@ void ustctl_init(void) ust_err_init(); lttng_ust_getenv_init(); /* Needs ust_err_init() to be completed. */ lttng_ust_clock_init(); - lttng_ring_buffer_metadata_client_init(); - lttng_ring_buffer_client_overwrite_init(); - lttng_ring_buffer_client_overwrite_rt_init(); - lttng_ring_buffer_client_discard_init(); - lttng_ring_buffer_client_discard_rt_init(); - lttng_counter_client_percpu_32_modular_init(); - lttng_counter_client_percpu_64_modular_init(); + lttng_ust_ring_buffer_clients_init(); + lttng_ust_counter_clients_init(); lib_ringbuffer_signal_init(); } static __attribute__((destructor)) void ustctl_exit(void) { - lttng_ring_buffer_client_discard_rt_exit(); - lttng_ring_buffer_client_discard_exit(); - lttng_ring_buffer_client_overwrite_rt_exit(); - lttng_ring_buffer_client_overwrite_exit(); - lttng_ring_buffer_metadata_client_exit(); - lttng_counter_client_percpu_32_modular_exit(); - lttng_counter_client_percpu_64_modular_exit(); + lttng_ust_counter_clients_exit(); + lttng_ust_ring_buffer_clients_exit(); } diff --git a/liblttng-ust/lttng-rb-clients.h b/liblttng-ust/lttng-rb-clients.h index 57d7cdfe..4b6999e4 100644 --- a/liblttng-ust/lttng-rb-clients.h +++ b/liblttng-ust/lttng-rb-clients.h @@ -39,4 +39,14 @@ struct lttng_ust_client_lib_ring_buffer_client_cb { struct lttng_ust_lib_ring_buffer_channel *chan, uint64_t *id); }; +/* + * The ring buffer and counter clients init/exit symbols are private ABI + * for liblttng-ust-ctl, which is why they are not hidden. + */ +void lttng_ust_ring_buffer_clients_init(void); +void lttng_ust_ring_buffer_clients_exit(void); + +void lttng_ust_counter_clients_init(void); +void lttng_ust_counter_clients_exit(void); + #endif /* _LTTNG_RB_CLIENT_H */ diff --git a/liblttng-ust/lttng-ring-buffer-client-discard-rt.c b/liblttng-ust/lttng-ring-buffer-client-discard-rt.c index 425515b6..0c5884b7 100644 --- a/liblttng-ust/lttng-ring-buffer-client-discard-rt.c +++ b/liblttng-ust/lttng-ring-buffer-client-discard-rt.c @@ -11,6 +11,8 @@ #define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD #define RING_BUFFER_MODE_TEMPLATE_STRING "discard-rt" +#define RING_BUFFER_MODE_TEMPLATE_TLS_FIXUP \ + lttng_ust_fixup_ring_buffer_client_discard_rt_tls #define RING_BUFFER_MODE_TEMPLATE_INIT \ lttng_ring_buffer_client_discard_rt_init #define RING_BUFFER_MODE_TEMPLATE_EXIT \ diff --git a/liblttng-ust/lttng-ring-buffer-client-discard.c b/liblttng-ust/lttng-ring-buffer-client-discard.c index 954303a8..82d25fd4 100644 --- a/liblttng-ust/lttng-ring-buffer-client-discard.c +++ b/liblttng-ust/lttng-ring-buffer-client-discard.c @@ -11,6 +11,8 @@ #define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD #define RING_BUFFER_MODE_TEMPLATE_STRING "discard" +#define RING_BUFFER_MODE_TEMPLATE_TLS_FIXUP \ + lttng_ust_fixup_ring_buffer_client_discard_tls #define RING_BUFFER_MODE_TEMPLATE_INIT \ lttng_ring_buffer_client_discard_init #define RING_BUFFER_MODE_TEMPLATE_EXIT \ diff --git a/liblttng-ust/lttng-ring-buffer-client-overwrite-rt.c b/liblttng-ust/lttng-ring-buffer-client-overwrite-rt.c index da568ee5..d0b9151b 100644 --- a/liblttng-ust/lttng-ring-buffer-client-overwrite-rt.c +++ b/liblttng-ust/lttng-ring-buffer-client-overwrite-rt.c @@ -11,6 +11,8 @@ #define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE #define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite-rt" +#define RING_BUFFER_MODE_TEMPLATE_TLS_FIXUP \ + lttng_ust_fixup_ring_buffer_client_overwrite_rt_tls #define RING_BUFFER_MODE_TEMPLATE_INIT \ lttng_ring_buffer_client_overwrite_rt_init #define RING_BUFFER_MODE_TEMPLATE_EXIT \ diff --git a/liblttng-ust/lttng-ring-buffer-client-overwrite.c b/liblttng-ust/lttng-ring-buffer-client-overwrite.c index 712e882c..2a92faba 100644 --- a/liblttng-ust/lttng-ring-buffer-client-overwrite.c +++ b/liblttng-ust/lttng-ring-buffer-client-overwrite.c @@ -11,6 +11,8 @@ #define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE #define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite" +#define RING_BUFFER_MODE_TEMPLATE_TLS_FIXUP \ + lttng_ust_fixup_ring_buffer_client_overwrite_tls #define RING_BUFFER_MODE_TEMPLATE_INIT \ lttng_ring_buffer_client_overwrite_init #define RING_BUFFER_MODE_TEMPLATE_EXIT \ diff --git a/liblttng-ust/lttng-ring-buffer-client.h b/liblttng-ust/lttng-ring-buffer-client.h index dc3dd88f..dfc98cee 100644 --- a/liblttng-ust/lttng-ring-buffer-client.h +++ b/liblttng-ust/lttng-ring-buffer-client.h @@ -78,8 +78,7 @@ static DEFINE_URCU_TLS(private_ctx_stack_t, private_ctx_stack); /* * Force a read (imply TLS fixup for dlopen) of TLS variables. */ -static -void lttng_fixup_rb_client_tls(void) +void RING_BUFFER_MODE_TEMPLATE_TLS_FIXUP(void) { asm volatile ("" : : "m" (URCU_TLS(private_ctx_stack))); } @@ -858,7 +857,6 @@ void RING_BUFFER_MODE_TEMPLATE_INIT(void) { DBG("LTT : ltt ring buffer client \"%s\" init\n", "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap"); - lttng_fixup_rb_client_tls(); lttng_transport_register(<tng_relay_transport); } diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index cb9f8c88..07ae9a34 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -351,17 +351,6 @@ static const char *cmd_name_mapping[] = { static const char *str_timeout; static int got_timeout_env; -extern void lttng_ring_buffer_client_overwrite_init(void); -extern void lttng_ring_buffer_client_overwrite_rt_init(void); -extern void lttng_ring_buffer_client_discard_init(void); -extern void lttng_ring_buffer_client_discard_rt_init(void); -extern void lttng_ring_buffer_metadata_client_init(void); -extern void lttng_ring_buffer_client_overwrite_exit(void); -extern void lttng_ring_buffer_client_overwrite_rt_exit(void); -extern void lttng_ring_buffer_client_discard_exit(void); -extern void lttng_ring_buffer_client_discard_rt_exit(void); -extern void lttng_ring_buffer_metadata_client_exit(void); - static char *get_map_shm(struct sock_info *sock_info); ssize_t lttng_ust_read(int fd, void *buf, size_t len) @@ -437,6 +426,31 @@ void lttng_ust_fixup_tls(void) lttng_fixup_net_ns_tls(); lttng_fixup_time_ns_tls(); lttng_fixup_uts_ns_tls(); + lttng_ust_fixup_ring_buffer_client_discard_tls(); + lttng_ust_fixup_ring_buffer_client_discard_rt_tls(); + lttng_ust_fixup_ring_buffer_client_overwrite_tls(); + lttng_ust_fixup_ring_buffer_client_overwrite_rt_tls(); +} + +/* + * LTTng-UST uses Global Dynamic model TLS variables rather than IE + * model because many versions of glibc don't preallocate a pool large + * enough for TLS variables IE model defined in other shared libraries, + * and causes issues when using LTTng-UST for Java tracing. + * + * Because of this use of Global Dynamic TLS variables, users wishing to + * trace from signal handlers need to explicitly trigger the lazy + * allocation of those variables for each thread before using them. + * This can be triggered by calling lttng_ust_init_thread(). + */ +void lttng_ust_init_thread(void) +{ + /* + * Because those TLS variables are global dynamic, we need to + * ensure those are initialized before a signal handler nesting over + * this thread attempts to use them. + */ + lttng_ust_fixup_tls(); } int lttng_get_notify_socket(void *owner) @@ -2048,6 +2062,36 @@ void lttng_ust_libc_wrapper_malloc_init(void) { } +void lttng_ust_ring_buffer_clients_init(void) +{ + lttng_ring_buffer_metadata_client_init(); + lttng_ring_buffer_client_overwrite_init(); + lttng_ring_buffer_client_overwrite_rt_init(); + lttng_ring_buffer_client_discard_init(); + lttng_ring_buffer_client_discard_rt_init(); +} + +void lttng_ust_ring_buffer_clients_exit(void) +{ + lttng_ring_buffer_client_discard_rt_exit(); + lttng_ring_buffer_client_discard_exit(); + lttng_ring_buffer_client_overwrite_rt_exit(); + lttng_ring_buffer_client_overwrite_exit(); + lttng_ring_buffer_metadata_client_exit(); +} + +void lttng_ust_counter_clients_init(void) +{ + lttng_counter_client_percpu_64_modular_init(); + lttng_counter_client_percpu_32_modular_init(); +} + +void lttng_ust_counter_clients_exit(void) +{ + lttng_counter_client_percpu_32_modular_exit(); + lttng_counter_client_percpu_64_modular_exit(); +} + /* * sessiond monitoring thread: monitor presence of global and per-user * sessiond by polling the application common named pipe. @@ -2106,13 +2150,8 @@ void __attribute__((constructor)) lttng_ust_init(void) lttng_ust_clock_init(); lttng_ust_getcpu_init(); lttng_ust_statedump_init(); - lttng_ring_buffer_metadata_client_init(); - lttng_ring_buffer_client_overwrite_init(); - lttng_ring_buffer_client_overwrite_rt_init(); - lttng_ring_buffer_client_discard_init(); - lttng_ring_buffer_client_discard_rt_init(); - lttng_counter_client_percpu_32_modular_init(); - lttng_counter_client_percpu_64_modular_init(); + lttng_ust_ring_buffer_clients_init(); + lttng_ust_counter_clients_init(); lttng_perf_counter_init(); /* * Invoke ust malloc wrapper init before starting other threads. @@ -2253,13 +2292,8 @@ void lttng_ust_cleanup(int exiting) lttng_ust_abi_exit(); lttng_ust_abi_events_exit(); lttng_perf_counter_exit(); - lttng_ring_buffer_client_discard_rt_exit(); - lttng_ring_buffer_client_discard_exit(); - lttng_ring_buffer_client_overwrite_rt_exit(); - lttng_ring_buffer_client_overwrite_exit(); - lttng_ring_buffer_metadata_client_exit(); - lttng_counter_client_percpu_32_modular_exit(); - lttng_counter_client_percpu_64_modular_exit(); + lttng_ust_ring_buffer_clients_exit(); + lttng_ust_counter_clients_exit(); lttng_ust_statedump_destroy(); lttng_ust_tp_exit(); if (!exiting) { diff --git a/liblttng-ust/ust-events-internal.h b/liblttng-ust/ust-events-internal.h index 055e4f6e..e8c44be4 100644 --- a/liblttng-ust/ust-events-internal.h +++ b/liblttng-ust/ust-events-internal.h @@ -908,4 +908,35 @@ __attribute__((visibility("hidden"))) void lttng_ust_format_event_name(const struct lttng_ust_event_desc *desc, char *name); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_overwrite_init(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_overwrite_rt_init(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_discard_init(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_discard_rt_init(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_metadata_client_init(void); + +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_overwrite_exit(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_overwrite_rt_exit(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_discard_exit(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_client_discard_rt_exit(void); +__attribute__((visibility("hidden"))) +void lttng_ring_buffer_metadata_client_exit(void); + +__attribute__((visibility("hidden"))) +void lttng_ust_fixup_ring_buffer_client_overwrite_tls(void); +__attribute__((visibility("hidden"))) +void lttng_ust_fixup_ring_buffer_client_overwrite_rt_tls(void); +__attribute__((visibility("hidden"))) +void lttng_ust_fixup_ring_buffer_client_discard_tls(void); +__attribute__((visibility("hidden"))) +void lttng_ust_fixup_ring_buffer_client_discard_rt_tls(void); + #endif /* _LTTNG_UST_EVENTS_INTERNAL_H */ -- 2.34.1