X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-comm.c;h=347a2e09fa3d5b5b61cf74eaf2f7a8fc99265156;hb=5287fad0d44dd62029a23d0b44fcd3c95574345a;hp=32ba3c1d49e2ba7bbec27ffb2f0d3f502d168653;hpb=f5c453e975e5d417590b9a1be2a9f8504db063c0;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 32ba3c1d..347a2e09 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -20,13 +20,15 @@ */ #define _LGPL_SOURCE -#define _GNU_SOURCE +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -37,9 +39,11 @@ #include #include #include -#include +#include "futex.h" #include +#include +#include #include #include #include @@ -58,6 +62,11 @@ #include "clock.h" #include "../libringbuffer/getcpu.h" #include "getenv.h" +#include "ust-events-internal.h" +#include "context-internal.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 ? @@ -82,6 +91,8 @@ static int initialized; * * ust_lock nests within the dynamic loader lock (within glibc) because * it is taken within the library constructor. + * + * The ust fd tracker lock nests within the ust_mutex. */ static pthread_mutex_t ust_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -224,7 +235,11 @@ static sem_t constructor_wait; /* * Doing this for both the global and local sessiond. */ -static int sem_count = { 2 }; +enum { + sem_count_initial_value = 4, +}; + +static int sem_count = sem_count_initial_value; /* * Counting nesting within lttng-ust. Used to ensure that calling fork() @@ -239,7 +254,7 @@ struct sock_info { const char *name; pthread_t ust_listener; /* listener thread */ int root_handle; - int constructor_sem_posted; + int registration_done; int allowed; int global; int thread_active; @@ -252,6 +267,9 @@ struct sock_info { char *wait_shm_mmap; /* Keep track of lazy state dump not performed yet. */ int statedump_pending; + int initial_statedump_done; + /* Keep procname for statedump */ + char procname[LTTNG_UST_ABI_PROCNAME_LEN]; }; /* Socket from app (connect) to session daemon (listen) for communication */ @@ -260,7 +278,8 @@ struct sock_info global_apps = { .global = 1, .root_handle = -1, - .allowed = 1, + .registration_done = 0, + .allowed = 0, .thread_active = 0, .sock_path = LTTNG_DEFAULT_RUNDIR "/" LTTNG_UST_SOCK_FILENAME, @@ -270,6 +289,8 @@ struct sock_info global_apps = { .wait_shm_path = "/" LTTNG_UST_WAIT_FILENAME, .statedump_pending = 0, + .initial_statedump_done = 0, + .procname[0] = '\0' }; /* TODO: allow global_apps_sock_path override */ @@ -278,6 +299,7 @@ struct sock_info local_apps = { .name = "local", .global = 0, .root_handle = -1, + .registration_done = 0, .allowed = 0, /* Check setuid bit first */ .thread_active = 0, @@ -285,6 +307,8 @@ struct sock_info local_apps = { .notify_socket = -1, .statedump_pending = 0, + .initial_statedump_done = 0, + .procname[0] = '\0' }; static int wait_poll_fallback; @@ -299,6 +323,8 @@ static const char *cmd_name_mapping[] = { [ LTTNG_UST_REGISTER_DONE ] = "Registration Done", [ LTTNG_UST_TRACEPOINT_FIELD_LIST ] = "Create Tracepoint Field List", + [ LTTNG_UST_EVENT_NOTIFIER_GROUP_CREATE ] = "Create event notifier group", + /* Session FD commands */ [ LTTNG_UST_CHANNEL ] = "Create Channel", [ LTTNG_UST_SESSION_START ] = "Start Session", @@ -323,6 +349,16 @@ static const char *cmd_name_mapping[] = { /* Event FD commands */ [ LTTNG_UST_FILTER ] = "Create Filter", [ LTTNG_UST_EXCLUSION ] = "Add exclusions to event", + + /* Event notifier group commands */ + [ LTTNG_UST_EVENT_NOTIFIER_CREATE ] = "Create event notifier", + + /* Session and event notifier group commands */ + [ LTTNG_UST_COUNTER ] = "Create Counter", + + /* Counter commands */ + [ LTTNG_UST_COUNTER_GLOBAL ] = "Create Counter Global", + [ LTTNG_UST_COUNTER_CPU ] = "Create Counter CPU", }; static const char *str_timeout; @@ -338,6 +374,16 @@ 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); +LTTNG_HIDDEN +extern void lttng_counter_client_percpu_32_modular_init(void); +LTTNG_HIDDEN +extern void lttng_counter_client_percpu_32_modular_exit(void); +LTTNG_HIDDEN +extern void lttng_counter_client_percpu_64_modular_init(void); +LTTNG_HIDDEN +extern void lttng_counter_client_percpu_64_modular_exit(void); + +static char *get_map_shm(struct sock_info *sock_info); ssize_t lttng_ust_read(int fd, void *buf, size_t len) { @@ -389,24 +435,29 @@ void lttng_fixup_ust_mutex_nest_tls(void) } /* - * Fixup urcu bp TLS. + * Fixup lttng-ust urcu TLS. */ static -void lttng_fixup_urcu_bp_tls(void) +void lttng_fixup_lttng_ust_urcu_tls(void) { - rcu_read_lock(); - rcu_read_unlock(); + (void) lttng_ust_urcu_read_ongoing(); } void lttng_ust_fixup_tls(void) { - lttng_fixup_urcu_bp_tls(); + lttng_fixup_lttng_ust_urcu_tls(); lttng_fixup_ringbuffer_tls(); lttng_fixup_vtid_tls(); lttng_fixup_nest_count_tls(); lttng_fixup_procname_tls(); lttng_fixup_ust_mutex_nest_tls(); + lttng_ust_fixup_perf_counter_tls(); lttng_ust_fixup_fd_tracker_tls(); + lttng_fixup_cgroup_ns_tls(); + lttng_fixup_ipc_ns_tls(); + lttng_fixup_net_ns_tls(); + lttng_fixup_time_ns_tls(); + lttng_fixup_uts_ns_tls(); } int lttng_get_notify_socket(void *owner) @@ -416,6 +467,15 @@ int lttng_get_notify_socket(void *owner) return info->notify_socket; } + +LTTNG_HIDDEN +char* lttng_ust_sockinfo_get_procname(void *owner) +{ + struct sock_info *info = owner; + + return info->procname; +} + static void print_cmd(int cmd, int handle) { @@ -430,25 +490,49 @@ void print_cmd(int cmd, int handle) 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; + lttng_pthread_getname_np(global_apps.procname, LTTNG_UST_ABI_PROCNAME_LEN); +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", @@ -458,7 +542,18 @@ int setup_local_apps(void) 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; + } + + lttng_pthread_getname_np(local_apps.procname, LTTNG_UST_ABI_PROCNAME_LEN); +end: + return ret; } /* @@ -583,46 +678,203 @@ int send_reply(int sock, struct ustcomm_ust_reply *lur) } static -int handle_register_done(struct sock_info *sock_info) +void decrement_sem_count(unsigned int count) { int ret; - if (sock_info->constructor_sem_posted) - return 0; - sock_info->constructor_sem_posted = 1; + assert(uatomic_read(&sem_count) >= count); + if (uatomic_read(&sem_count) <= 0) { - return 0; + return; } - ret = uatomic_add_return(&sem_count, -1); + + ret = uatomic_add_return(&sem_count, -count); if (ret == 0) { ret = sem_post(&constructor_wait); assert(!ret); } +} + +static +int handle_register_done(struct sock_info *sock_info) +{ + if (sock_info->registration_done) + return 0; + sock_info->registration_done = 1; + + decrement_sem_count(1); + if (!sock_info->statedump_pending) { + sock_info->initial_statedump_done = 1; + decrement_sem_count(1); + } + + return 0; +} + +static +int handle_register_failed(struct sock_info *sock_info) +{ + if (sock_info->registration_done) + return 0; + sock_info->registration_done = 1; + sock_info->initial_statedump_done = 1; + + decrement_sem_count(2); + return 0; } /* * Only execute pending statedump after the constructor semaphore has - * been posted by each listener thread. This means statedump will only - * be performed after the "registration done" command is received from - * each session daemon the application is connected to. + * been posted by the current listener thread. This means statedump will + * only be performed after the "registration done" command is received + * from this thread's session daemon. * * This ensures we don't run into deadlock issues with the dynamic * loader mutex, which is held while the constructor is called and * waiting on the constructor semaphore. All operations requiring this * dynamic loader lock need to be postponed using this mechanism. + * + * In a scenario with two session daemons connected to the application, + * it is possible that the first listener thread which receives the + * registration done command issues its statedump while the dynamic + * loader lock is still held by the application constructor waiting on + * the semaphore. It will however be allowed to proceed when the + * second session daemon sends the registration done command to the + * second listener thread. This situation therefore does not produce + * a deadlock. */ static void handle_pending_statedump(struct sock_info *sock_info) { - int ctor_passed = sock_info->constructor_sem_posted; - - if (ctor_passed && sock_info->statedump_pending) { + if (sock_info->registration_done && sock_info->statedump_pending) { sock_info->statedump_pending = 0; pthread_mutex_lock(&ust_fork_mutex); lttng_handle_pending_statedump(sock_info); pthread_mutex_unlock(&ust_fork_mutex); + + if (!sock_info->initial_statedump_done) { + sock_info->initial_statedump_done = 1; + decrement_sem_count(1); + } + } +} + +static inline +const char *bytecode_type_str(uint32_t cmd) +{ + switch (cmd) { + case LTTNG_UST_CAPTURE: + return "capture"; + case LTTNG_UST_FILTER: + return "filter"; + default: + abort(); + } +} + +static +int handle_bytecode_recv(struct sock_info *sock_info, + int sock, struct ustcomm_ust_msg *lum) +{ + struct lttng_ust_bytecode_node *bytecode = NULL; + enum lttng_ust_bytecode_node_type type; + const struct lttng_ust_objd_ops *ops; + uint32_t data_size, data_size_max, reloc_offset; + uint64_t seqnum; + ssize_t len; + int ret = 0; + + switch (lum->cmd) { + case LTTNG_UST_FILTER: + type = LTTNG_UST_BYTECODE_NODE_TYPE_FILTER; + data_size = lum->u.filter.data_size; + data_size_max = FILTER_BYTECODE_MAX_LEN; + reloc_offset = lum->u.filter.reloc_offset; + seqnum = lum->u.filter.seqnum; + break; + case LTTNG_UST_CAPTURE: + type = LTTNG_UST_BYTECODE_NODE_TYPE_CAPTURE; + data_size = lum->u.capture.data_size; + data_size_max = CAPTURE_BYTECODE_MAX_LEN; + reloc_offset = lum->u.capture.reloc_offset; + seqnum = lum->u.capture.seqnum; + break; + default: + abort(); + } + + if (data_size > data_size_max) { + ERR("Bytecode %s data size is too large: %u bytes", + bytecode_type_str(lum->cmd), data_size); + ret = -EINVAL; + goto end; + } + + if (reloc_offset > data_size) { + ERR("Bytecode %s reloc offset %u is not within data", + bytecode_type_str(lum->cmd), reloc_offset); + ret = -EINVAL; + goto end; + } + + /* Allocate the structure AND the `data[]` field. */ + bytecode = zmalloc(sizeof(*bytecode) + data_size); + if (!bytecode) { + ret = -ENOMEM; + goto end; + } + + bytecode->bc.len = data_size; + bytecode->bc.reloc_offset = reloc_offset; + bytecode->bc.seqnum = seqnum; + bytecode->type = type; + + len = ustcomm_recv_unix_sock(sock, bytecode->bc.data, bytecode->bc.len); + switch (len) { + case 0: /* orderly shutdown */ + ret = 0; + goto end; + default: + if (len == bytecode->bc.len) { + DBG("Bytecode %s data received", + bytecode_type_str(lum->cmd)); + break; + } else if (len < 0) { + DBG("Receive failed from lttng-sessiond with errno %d", + (int) -len); + if (len == -ECONNRESET) { + ERR("%s remote end closed connection", + sock_info->name); + ret = len; + goto end; + } + ret = len; + goto end; + } else { + DBG("Incorrect %s bytecode data message size: %zd", + bytecode_type_str(lum->cmd), len); + ret = -EINVAL; + goto end; + } + } + + ops = objd_ops(lum->handle); + if (!ops) { + ret = -ENOENT; + goto end; } + + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &bytecode, + NULL, sock_info); + else + ret = -ENOSYS; + +end: + free(bytecode); + return ret; } static @@ -662,76 +914,12 @@ int handle_message(struct sock_info *sock_info, else ret = lttng_ust_objd_unref(lum->handle, 1); break; + case LTTNG_UST_CAPTURE: case LTTNG_UST_FILTER: - { - /* Receive filter data */ - struct lttng_ust_filter_bytecode_node *bytecode; - - if (lum->u.filter.data_size > FILTER_BYTECODE_MAX_LEN) { - ERR("Filter data size is too large: %u bytes", - lum->u.filter.data_size); - ret = -EINVAL; - goto error; - } - - if (lum->u.filter.reloc_offset > lum->u.filter.data_size) { - ERR("Filter reloc offset %u is not within data", - lum->u.filter.reloc_offset); - ret = -EINVAL; - goto error; - } - - bytecode = zmalloc(sizeof(*bytecode) + lum->u.filter.data_size); - if (!bytecode) { - ret = -ENOMEM; - goto error; - } - len = ustcomm_recv_unix_sock(sock, bytecode->bc.data, - lum->u.filter.data_size); - switch (len) { - case 0: /* orderly shutdown */ - ret = 0; - free(bytecode); + ret = handle_bytecode_recv(sock_info, sock, lum); + if (ret) goto error; - default: - if (len == lum->u.filter.data_size) { - DBG("filter data received"); - break; - } else if (len < 0) { - DBG("Receive failed from lttng-sessiond with errno %d", (int) -len); - if (len == -ECONNRESET) { - ERR("%s remote end closed connection", sock_info->name); - ret = len; - free(bytecode); - goto error; - } - ret = len; - free(bytecode); - goto error; - } else { - DBG("incorrect filter data message size: %zd", len); - ret = -EINVAL; - free(bytecode); - goto error; - } - } - bytecode->bc.len = lum->u.filter.data_size; - bytecode->bc.reloc_offset = lum->u.filter.reloc_offset; - bytecode->bc.seqnum = lum->u.filter.seqnum; - if (ops->cmd) { - ret = ops->cmd(lum->handle, lum->cmd, - (unsigned long) bytecode, - &args, sock_info); - if (ret) { - free(bytecode); - } - /* don't free bytecode if everything went fine. */ - } else { - ret = -ENOSYS; - free(bytecode); - } break; - } case LTTNG_UST_EXCLUSION: { /* Receive exclusion names */ @@ -780,17 +968,60 @@ int handle_message(struct sock_info *sock_info, goto error; } } - if (ops->cmd) { + if (ops->cmd) ret = ops->cmd(lum->handle, lum->cmd, - (unsigned long) node, + (unsigned long) &node, &args, sock_info); - if (ret) { - free(node); + else + ret = -ENOSYS; + free(node); + break; + } + case LTTNG_UST_EVENT_NOTIFIER_GROUP_CREATE: + { + int event_notifier_notif_fd, close_ret; + + len = ustcomm_recv_event_notifier_notif_fd_from_sessiond(sock, + &event_notifier_notif_fd); + switch (len) { + case 0: /* orderly shutdown */ + ret = 0; + goto error; + case 1: + break; + default: + if (len < 0) { + DBG("Receive failed from lttng-sessiond with errno %d", + (int) -len); + if (len == -ECONNRESET) { + ERR("%s remote end closed connection", + sock_info->name); + ret = len; + goto error; + } + ret = len; + goto error; + } else { + DBG("Incorrect event notifier fd message size: %zd", + len); + ret = -EINVAL; + goto error; } - /* Don't free exclusion data if everything went fine. */ - } else { + } + args.event_notifier_handle.event_notifier_notif_fd = + event_notifier_notif_fd; + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &lum->u, + &args, sock_info); + else ret = -ENOSYS; - free(node); + if (args.event_notifier_handle.event_notifier_notif_fd >= 0) { + lttng_ust_lock_fd_tracker(); + close_ret = close(args.event_notifier_handle.event_notifier_notif_fd); + lttng_ust_unlock_fd_tracker(); + if (close_ret) + PERROR("close"); } break; } @@ -833,24 +1064,54 @@ int handle_message(struct sock_info *sock_info, &args, sock_info); else ret = -ENOSYS; + if (args.channel.wakeup_fd >= 0) { + int close_ret; + + lttng_ust_lock_fd_tracker(); + close_ret = close(args.channel.wakeup_fd); + lttng_ust_unlock_fd_tracker(); + args.channel.wakeup_fd = -1; + if (close_ret) + PERROR("close"); + } + free(args.channel.chan_data); break; } case LTTNG_UST_STREAM: { + int close_ret; + /* Receive shm_fd, wakeup_fd */ ret = ustcomm_recv_stream_from_sessiond(sock, - &lum->u.stream.len, + NULL, &args.stream.shm_fd, &args.stream.wakeup_fd); if (ret) { goto error; } + if (ops->cmd) ret = ops->cmd(lum->handle, lum->cmd, (unsigned long) &lum->u, &args, sock_info); else ret = -ENOSYS; + if (args.stream.shm_fd >= 0) { + lttng_ust_lock_fd_tracker(); + close_ret = close(args.stream.shm_fd); + lttng_ust_unlock_fd_tracker(); + args.stream.shm_fd = -1; + if (close_ret) + PERROR("close"); + } + if (args.stream.wakeup_fd >= 0) { + lttng_ust_lock_fd_tracker(); + close_ret = close(args.stream.wakeup_fd); + lttng_ust_unlock_fd_tracker(); + args.stream.wakeup_fd = -1; + if (close_ret) + PERROR("close"); + } break; } case LTTNG_UST_CONTEXT: @@ -911,6 +1172,142 @@ int handle_message(struct sock_info *sock_info, ret = -ENOSYS; } break; + case LTTNG_UST_COUNTER: + { + void *counter_data; + + len = ustcomm_recv_counter_from_sessiond(sock, + &counter_data, lum->u.counter.len); + switch (len) { + case 0: /* orderly shutdown */ + ret = 0; + goto error; + default: + if (len == lum->u.counter.len) { + DBG("counter data received"); + break; + } else if (len < 0) { + DBG("Receive failed from lttng-sessiond with errno %d", (int) -len); + if (len == -ECONNRESET) { + ERR("%s remote end closed connection", sock_info->name); + ret = len; + goto error; + } + ret = len; + goto error; + } else { + DBG("incorrect counter data message size: %zd", len); + ret = -EINVAL; + goto error; + } + } + args.counter.counter_data = counter_data; + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &lum->u, + &args, sock_info); + else + ret = -ENOSYS; + free(args.counter.counter_data); + break; + } + case LTTNG_UST_COUNTER_GLOBAL: + { + /* Receive shm_fd */ + ret = ustcomm_recv_counter_shm_from_sessiond(sock, + &args.counter_shm.shm_fd); + if (ret) { + goto error; + } + + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &lum->u, + &args, sock_info); + else + ret = -ENOSYS; + if (args.counter_shm.shm_fd >= 0) { + int close_ret; + + lttng_ust_lock_fd_tracker(); + close_ret = close(args.counter_shm.shm_fd); + lttng_ust_unlock_fd_tracker(); + args.counter_shm.shm_fd = -1; + if (close_ret) + PERROR("close"); + } + break; + } + case LTTNG_UST_COUNTER_CPU: + { + /* Receive shm_fd */ + ret = ustcomm_recv_counter_shm_from_sessiond(sock, + &args.counter_shm.shm_fd); + if (ret) { + goto error; + } + + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &lum->u, + &args, sock_info); + else + ret = -ENOSYS; + if (args.counter_shm.shm_fd >= 0) { + int close_ret; + + lttng_ust_lock_fd_tracker(); + close_ret = close(args.counter_shm.shm_fd); + lttng_ust_unlock_fd_tracker(); + args.counter_shm.shm_fd = -1; + if (close_ret) + PERROR("close"); + } + break; + } + case LTTNG_UST_EVENT_NOTIFIER_CREATE: + { + /* Receive struct lttng_ust_event_notifier */ + struct lttng_ust_event_notifier event_notifier; + + if (sizeof(event_notifier) != lum->u.event_notifier.len) { + DBG("incorrect event notifier data message size: %u", lum->u.event_notifier.len); + ret = -EINVAL; + goto error; + } + len = ustcomm_recv_unix_sock(sock, &event_notifier, sizeof(event_notifier)); + switch (len) { + case 0: /* orderly shutdown */ + ret = 0; + goto error; + default: + if (len == sizeof(event_notifier)) { + DBG("event notifier data received"); + break; + } else if (len < 0) { + DBG("Receive failed from lttng-sessiond with errno %d", (int) -len); + if (len == -ECONNRESET) { + ERR("%s remote end closed connection", sock_info->name); + ret = len; + goto error; + } + ret = len; + goto error; + } else { + DBG("incorrect event notifier data message size: %zd", len); + ret = -EINVAL; + goto error; + } + } + if (ops->cmd) + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) &event_notifier, + &args, sock_info); + else + ret = -ENOSYS; + break; + } + default: if (ops->cmd) ret = ops->cmd(lum->handle, lum->cmd, @@ -1030,7 +1427,8 @@ void cleanup_sock_info(struct sock_info *sock_info, int exiting) } sock_info->root_handle = -1; } - sock_info->constructor_sem_posted = 0; + sock_info->registration_done = 0; + sock_info->initial_statedump_done = 0; /* * wait_shm_mmap, socket and notify socket are used by listener @@ -1059,7 +1457,7 @@ void cleanup_sock_info(struct sock_info *sock_info, int exiting) if (sock_info->wait_shm_mmap) { long page_size; - page_size = sysconf(_SC_PAGE_SIZE); + page_size = LTTNG_UST_PAGE_SIZE; if (page_size <= 0) { if (!page_size) { errno = EINVAL; @@ -1301,25 +1699,23 @@ error: 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)) goto end_wait; - while (futex_async((int32_t *) sock_info->wait_shm_mmap, + while (lttng_ust_futex_async((int32_t *) sock_info->wait_shm_mmap, FUTEX_WAIT, 0, NULL, NULL, 0)) { switch (errno) { case EWOULDBLOCK: @@ -1396,6 +1792,10 @@ restart: prev_connect_failed = 0; } + if (ust_lock()) { + goto quit; + } + if (sock_info->socket != -1) { /* FD tracker is updated by ustcomm_close_unix_sock() */ ret = ustcomm_close_unix_sock(sock_info->socket); @@ -1415,9 +1815,6 @@ restart: sock_info->notify_socket = -1; } - if (ust_lock()) { - goto quit; - } /* * Register. We need to perform both connect and sending @@ -1439,7 +1836,7 @@ restart: * If we cannot find the sessiond daemon, don't delay * constructor execution. */ - ret = handle_register_done(sock_info); + ret = handle_register_failed(sock_info); assert(!ret); ust_unlock(); goto restart; @@ -1493,7 +1890,7 @@ restart: * If we cannot register to the sessiond daemon, don't * delay constructor execution. */ - ret = handle_register_done(sock_info); + ret = handle_register_failed(sock_info); assert(!ret); ust_unlock(); goto restart; @@ -1522,7 +1919,7 @@ restart: * If we cannot find the sessiond daemon, don't delay * constructor execution. */ - ret = handle_register_done(sock_info); + ret = handle_register_failed(sock_info); assert(!ret); ust_unlock(); goto restart; @@ -1586,7 +1983,7 @@ restart: * If we cannot register to the sessiond daemon, don't * delay constructor execution. */ - ret = handle_register_done(sock_info); + ret = handle_register_failed(sock_info); assert(!ret); ust_unlock(); goto restart; @@ -1616,7 +2013,7 @@ restart: * If we cannot register to the sessiond daemon, don't * delay constructor execution. */ - ret = handle_register_done(sock_info); + ret = handle_register_failed(sock_info); assert(!ret); ust_unlock(); goto end; @@ -1684,6 +2081,7 @@ void __attribute__((constructor)) lttng_ust_init(void) pthread_attr_t thread_attr; int timeout_mode; int ret; + void *handle; if (uatomic_xchg(&initialized, 1) == 1) return; @@ -1697,6 +2095,26 @@ void __attribute__((constructor)) lttng_ust_init(void) 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 @@ -1715,6 +2133,8 @@ void __attribute__((constructor)) lttng_ust_init(void) 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_perf_counter_init(); /* * Invoke ust malloc wrapper init before starting other threads. @@ -1730,8 +2150,15 @@ void __attribute__((constructor)) lttng_ust_init(void) 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); } @@ -1755,14 +2182,18 @@ void __attribute__((constructor)) lttng_ust_init(void) 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); @@ -1833,6 +2264,7 @@ void lttng_ust_cleanup(int exiting) 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 @@ -1848,11 +2280,13 @@ void lttng_ust_cleanup(int exiting) 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_statedump_destroy(); exit_tracepoint(); if (!exiting) { /* Reinitialize values for fork */ - sem_count = 2; + sem_count = sem_count_initial_value; lttng_ust_comm_should_quit = 0; initialized = 0; } @@ -1910,6 +2344,35 @@ void __attribute__((destructor)) lttng_ust_exit(void) lttng_ust_cleanup(1); } +static +void ust_context_ns_reset(void) +{ + lttng_context_pid_ns_reset(); + lttng_context_cgroup_ns_reset(); + lttng_context_ipc_ns_reset(); + lttng_context_mnt_ns_reset(); + lttng_context_net_ns_reset(); + lttng_context_user_ns_reset(); + lttng_context_time_ns_reset(); + lttng_context_uts_ns_reset(); +} + +static +void ust_context_vuids_reset(void) +{ + lttng_context_vuid_reset(); + lttng_context_veuid_reset(); + lttng_context_vsuid_reset(); +} + +static +void ust_context_vgids_reset(void) +{ + lttng_context_vgid_reset(); + lttng_context_vegid_reset(); + lttng_context_vsgid_reset(); +} + /* * We exclude the worker threads across fork and clone (except * CLONE_VM), because these system calls only keep the forking thread @@ -1943,7 +2406,9 @@ void ust_before_fork(sigset_t *save_sigset) pthread_mutex_lock(&ust_fork_mutex); ust_lock_nocheck(); - rcu_bp_before_fork(); + lttng_ust_urcu_before_fork(); + lttng_ust_lock_fd_tracker(); + lttng_perf_lock(); } static void ust_after_fork_common(sigset_t *restore_sigset) @@ -1951,6 +2416,8 @@ static void ust_after_fork_common(sigset_t *restore_sigset) int ret; DBG("process %d", getpid()); + lttng_perf_unlock(); + lttng_ust_unlock_fd_tracker(); ust_unlock(); pthread_mutex_unlock(&ust_fork_mutex); @@ -1967,7 +2434,7 @@ void ust_after_fork_parent(sigset_t *restore_sigset) if (URCU_TLS(lttng_ust_nest_count)) return; DBG("process %d", getpid()); - rcu_bp_after_fork_parent(); + lttng_ust_urcu_after_fork_parent(); /* Release mutexes and reenable signals */ ust_after_fork_common(restore_sigset); } @@ -1985,16 +2452,75 @@ void ust_after_fork_child(sigset_t *restore_sigset) { if (URCU_TLS(lttng_ust_nest_count)) return; + lttng_context_vpid_reset(); lttng_context_vtid_reset(); + lttng_context_procname_reset(); + ust_context_ns_reset(); + ust_context_vuids_reset(); + ust_context_vgids_reset(); DBG("process %d", getpid()); /* Release urcu mutexes */ - rcu_bp_after_fork_child(); + lttng_ust_urcu_after_fork_child(); lttng_ust_cleanup(0); /* Release mutexes and reenable signals */ ust_after_fork_common(restore_sigset); lttng_ust_init(); } +void ust_after_setns(void) +{ + ust_context_ns_reset(); + ust_context_vuids_reset(); + ust_context_vgids_reset(); +} + +void ust_after_unshare(void) +{ + ust_context_ns_reset(); + ust_context_vuids_reset(); + ust_context_vgids_reset(); +} + +void ust_after_setuid(void) +{ + ust_context_vuids_reset(); +} + +void ust_after_seteuid(void) +{ + ust_context_vuids_reset(); +} + +void ust_after_setreuid(void) +{ + ust_context_vuids_reset(); +} + +void ust_after_setresuid(void) +{ + ust_context_vuids_reset(); +} + +void ust_after_setgid(void) +{ + ust_context_vgids_reset(); +} + +void ust_after_setegid(void) +{ + ust_context_vgids_reset(); +} + +void ust_after_setregid(void) +{ + ust_context_vgids_reset(); +} + +void ust_after_setresgid(void) +{ + ust_context_vgids_reset(); +} + void lttng_ust_sockinfo_session_enabled(void *owner) { struct sock_info *sock_info = owner;