X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-comm.c;h=af8636a812eb438c34c48deb1e4349ca9dd17fc1;hb=c0c0989ab70574e09b2f7e8b48c2da6af664a849;hp=a09f676a42978146fd8d7d12b1e2638738c37334;hpb=d6ddec3f8a747381dfb2af999731b83379713960;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index a09f676a..af8636a8 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -1,26 +1,13 @@ /* - * lttng-ust-comm.c + * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (C) 2011 David Goulet * Copyright (C) 2011 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; only - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _LGPL_SOURCE -#define _GNU_SOURCE +#include +#include #include #include #include @@ -38,9 +25,11 @@ #include #include #include -#include +#include "futex.h" #include +#include +#include #include #include #include @@ -59,9 +48,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." LTTNG_UST_LIBRARY_VERSION_MAJOR +#define LTTNG_UST_LIB_SO_NAME "liblttng-ust.so." __ust_stringify(CONFIG_LTTNG_UST_LIBRARY_VERSION_MAJOR) /* * Has lttng ust comm constructor been called ? @@ -86,6 +77,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; @@ -228,7 +221,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() @@ -243,7 +240,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; @@ -256,6 +253,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 */ @@ -264,7 +264,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, @@ -274,6 +275,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 */ @@ -282,6 +285,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, @@ -289,6 +293,8 @@ struct sock_info local_apps = { .notify_socket = -1, .statedump_pending = 0, + .initial_statedump_done = 0, + .procname[0] = '\0' }; static int wait_poll_fallback; @@ -303,6 +309,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", @@ -327,6 +335,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; @@ -342,6 +360,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) { @@ -393,24 +421,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) @@ -420,6 +453,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) { @@ -434,25 +476,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", @@ -462,7 +528,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; } /* @@ -587,48 +664,205 @@ 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 int handle_message(struct sock_info *sock_info, int sock, struct ustcomm_ust_msg *lum) @@ -666,76 +900,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 */ @@ -784,17 +954,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; } @@ -837,24 +1050,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: @@ -915,6 +1158,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, @@ -1034,7 +1413,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 @@ -1063,7 +1443,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; @@ -1305,25 +1685,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: @@ -1444,7 +1822,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; @@ -1498,7 +1876,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; @@ -1527,7 +1905,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; @@ -1591,7 +1969,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; @@ -1621,7 +1999,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; @@ -1741,6 +2119,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. @@ -1756,8 +2136,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); } @@ -1781,14 +2168,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); @@ -1859,6 +2250,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 @@ -1874,11 +2266,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; } @@ -1936,6 +2330,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 @@ -1969,7 +2392,9 @@ void ust_before_fork(sigset_t *save_sigset) pthread_mutex_lock(&ust_fork_mutex); ust_lock_nocheck(); - urcu_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) @@ -1977,6 +2402,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); @@ -1993,7 +2420,7 @@ void ust_after_fork_parent(sigset_t *restore_sigset) if (URCU_TLS(lttng_ust_nest_count)) return; DBG("process %d", getpid()); - urcu_bp_after_fork_parent(); + lttng_ust_urcu_after_fork_parent(); /* Release mutexes and reenable signals */ ust_after_fork_common(restore_sigset); } @@ -2014,15 +2441,72 @@ void ust_after_fork_child(sigset_t *restore_sigset) 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 */ - urcu_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;