#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <dlfcn.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "../libringbuffer/getcpu.h"
#include "getenv.h"
+/* Concatenate lttng ust shared library name with its major version number. */
+#define LTTNG_UST_LIB_SO_NAME "liblttng-ust.so." __ust_stringify(CONFIG_LTTNG_UST_LIBRARY_VERSION_MAJOR)
+
/*
* Has lttng ust comm constructor been called ?
*/
.global = 1,
.root_handle = -1,
- .allowed = 1,
+ .allowed = 0,
.thread_active = 0,
.sock_path = LTTNG_DEFAULT_RUNDIR "/" LTTNG_UST_SOCK_FILENAME,
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)
{
ssize_t ret;
lttng_ust_obj_get_name(handle), handle);
}
+static
+int setup_global_apps(void)
+{
+ int ret = 0;
+ assert(!global_apps.wait_shm_mmap);
+
+ global_apps.wait_shm_mmap = get_map_shm(&global_apps);
+ if (!global_apps.wait_shm_mmap) {
+ WARN("Unable to get map shm for global apps. Disabling LTTng-UST global tracing.");
+ global_apps.allowed = 0;
+ ret = -EIO;
+ goto error;
+ }
+
+ global_apps.allowed = 1;
+error:
+ return ret;
+}
static
int setup_local_apps(void)
{
+ int ret = 0;
const char *home_dir;
uid_t uid;
+ assert(!local_apps.wait_shm_mmap);
+
uid = getuid();
/*
* Disallow per-user tracing for setuid binaries.
*/
if (uid != geteuid()) {
assert(local_apps.allowed == 0);
- return 0;
+ ret = 0;
+ goto end;
}
home_dir = get_lttng_home_dir();
if (!home_dir) {
WARN("HOME environment variable not set. Disabling LTTng-UST per-user tracing.");
assert(local_apps.allowed == 0);
- return -ENOENT;
+ ret = -ENOENT;
+ goto end;
}
local_apps.allowed = 1;
snprintf(local_apps.sock_path, PATH_MAX, "%s/%s/%s",
snprintf(local_apps.wait_shm_path, PATH_MAX, "/%s-%u",
LTTNG_UST_WAIT_FILENAME,
uid);
- return 0;
+
+ local_apps.wait_shm_mmap = get_map_shm(&local_apps);
+ if (!local_apps.wait_shm_mmap) {
+ WARN("Unable to get map shm for local apps. Disabling LTTng-UST per-user tracing.");
+ local_apps.allowed = 0;
+ ret = -EIO;
+ goto end;
+ }
+end:
+ return ret;
}
/*
static
void wait_for_sessiond(struct sock_info *sock_info)
{
+ /* Use ust_lock to check if we should quit. */
if (ust_lock()) {
goto quit;
}
if (wait_poll_fallback) {
goto error;
}
- if (!sock_info->wait_shm_mmap) {
- sock_info->wait_shm_mmap = get_map_shm(sock_info);
- if (!sock_info->wait_shm_mmap)
- goto error;
- }
ust_unlock();
+ assert(sock_info->wait_shm_mmap);
+
DBG("Waiting for %s apps sessiond", sock_info->name);
/* Wait for futex wakeup */
if (uatomic_read((int32_t *) sock_info->wait_shm_mmap))
pthread_attr_t thread_attr;
int timeout_mode;
int ret;
+ void *handle;
if (uatomic_xchg(&initialized, 1) == 1)
return;
lttng_ust_loaded = 1;
+ /*
+ * We need to ensure that the liblttng-ust library is not unloaded to avoid
+ * the unloading of code used by the ust_listener_threads as we can not
+ * reliably know when they exited. To do that, manually load
+ * liblttng-ust.so to increment the dynamic loader's internal refcount for
+ * this library so it never becomes zero, thus never gets unloaded from the
+ * address space of the process. Since we are already running in the
+ * constructor of the LTTNG_UST_LIB_SO_NAME library, calling dlopen will
+ * simply increment the refcount and no additionnal work is needed by the
+ * dynamic loader as the shared library is already loaded in the address
+ * space. As a safe guard, we use the RTLD_NODELETE flag to prevent
+ * unloading of the UST library if its refcount becomes zero (which should
+ * never happen). Do the return value check but discard the handle at the
+ * end of the function as it's not needed.
+ */
+ handle = dlopen(LTTNG_UST_LIB_SO_NAME, RTLD_LAZY | RTLD_NODELETE);
+ if (!handle) {
+ ERR("dlopen of liblttng-ust shared library (%s).", LTTNG_UST_LIB_SO_NAME);
+ }
+
/*
* We want precise control over the order in which we construct
* our sub-libraries vs starting to receive commands from
PERROR("sem_init");
}
+ ret = setup_global_apps();
+ if (ret) {
+ assert(global_apps.allowed == 0);
+ DBG("global apps setup returned %d", ret);
+ }
+
ret = setup_local_apps();
if (ret) {
+ assert(local_apps.allowed == 0);
DBG("local apps setup returned %d", ret);
}
ERR("pthread_attr_setdetachstate: %s", strerror(ret));
}
- pthread_mutex_lock(&ust_exit_mutex);
- ret = pthread_create(&global_apps.ust_listener, &thread_attr,
- ust_listener_thread, &global_apps);
- if (ret) {
- ERR("pthread_create global: %s", strerror(ret));
+ if (global_apps.allowed) {
+ pthread_mutex_lock(&ust_exit_mutex);
+ ret = pthread_create(&global_apps.ust_listener, &thread_attr,
+ ust_listener_thread, &global_apps);
+ if (ret) {
+ ERR("pthread_create global: %s", strerror(ret));
+ }
+ global_apps.thread_active = 1;
+ pthread_mutex_unlock(&ust_exit_mutex);
+ } else {
+ handle_register_done(&global_apps);
}
- global_apps.thread_active = 1;
- pthread_mutex_unlock(&ust_exit_mutex);
if (local_apps.allowed) {
pthread_mutex_lock(&ust_exit_mutex);
cleanup_sock_info(&global_apps, exiting);
cleanup_sock_info(&local_apps, exiting);
local_apps.allowed = 0;
+ global_apps.allowed = 0;
/*
* The teardown in this function all affect data structures
* accessed under the UST lock by the listener thread. This
pthread_mutex_lock(&ust_fork_mutex);
ust_lock_nocheck();
- rcu_bp_before_fork();
+ urcu_bp_before_fork();
}
static void ust_after_fork_common(sigset_t *restore_sigset)
if (URCU_TLS(lttng_ust_nest_count))
return;
DBG("process %d", getpid());
- rcu_bp_after_fork_parent();
+ urcu_bp_after_fork_parent();
/* Release mutexes and reenable signals */
ust_after_fork_common(restore_sigset);
}
{
if (URCU_TLS(lttng_ust_nest_count))
return;
+ lttng_context_vpid_reset();
lttng_context_vtid_reset();
+ lttng_context_procname_reset();
DBG("process %d", getpid());
/* Release urcu mutexes */
- rcu_bp_after_fork_child();
+ urcu_bp_after_fork_child();
lttng_ust_cleanup(0);
/* Release mutexes and reenable signals */
ust_after_fork_common(restore_sigset);