X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-comm.c;h=86cce18d57fe658588db907ed8016f39e95f975f;hb=efe0de097e8e1cd372a7eb926e0ec68b97e6ee50;hp=6830d86d100ac4ad4e49b5458f2518b463d609cc;hpb=cbef69018acdeb52d27529e80126b43f3733e233;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 6830d86d..86cce18d 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -22,7 +22,6 @@ #define _LGPL_SOURCE #include #include -#include #include #include #include @@ -46,6 +45,7 @@ #include #include "tracepoint-internal.h" #include "ltt-tracer-core.h" +#include "compat.h" /* * Has lttng ust comm constructor been called ? @@ -159,7 +159,6 @@ static int register_app_to_sessiond(int socket) { ssize_t ret; - int prctl_ret; struct { uint32_t major; uint32_t minor; @@ -178,11 +177,7 @@ int register_app_to_sessiond(int socket) reg_msg.uid = getuid(); reg_msg.gid = getgid(); reg_msg.bits_per_long = CAA_BITS_PER_LONG; - prctl_ret = prctl(PR_GET_NAME, (unsigned long) reg_msg.name, 0, 0, 0); - if (prctl_ret) { - ERR("Error executing prctl"); - return -errno; - } + lttng_ust_getprocname(reg_msg.name); ret = ustcomm_send_unix_sock(socket, ®_msg, sizeof(reg_msg)); if (ret >= 0 && ret != sizeof(reg_msg)) @@ -239,6 +234,7 @@ int handle_message(struct sock_info *sock_info, const struct lttng_ust_objd_ops *ops; struct ustcomm_ust_reply lur; int shm_fd, wait_fd; + union ust_args args; ust_lock(); @@ -271,7 +267,8 @@ int handle_message(struct sock_info *sock_info, default: if (ops->cmd) ret = ops->cmd(lum->handle, lum->cmd, - (unsigned long) &lum->u); + (unsigned long) &lum->u, + &args); else ret = -ENOSYS; break; @@ -293,15 +290,15 @@ end: * Special-case reply to send stream info. * Use lum.u output. */ - lur.u.stream.memory_map_size = lum->u.stream.memory_map_size; - shm_fd = lum->u.stream.shm_fd; - wait_fd = lum->u.stream.wait_fd; + lur.u.stream.memory_map_size = *args.stream.memory_map_size; + shm_fd = *args.stream.shm_fd; + wait_fd = *args.stream.wait_fd; break; case LTTNG_UST_METADATA: case LTTNG_UST_CHANNEL: - lur.u.channel.memory_map_size = lum->u.channel.memory_map_size; - shm_fd = lum->u.channel.shm_fd; - wait_fd = lum->u.channel.wait_fd; + lur.u.channel.memory_map_size = *args.channel.memory_map_size; + shm_fd = *args.channel.shm_fd; + wait_fd = *args.channel.wait_fd; break; case LTTNG_UST_TRACER_VERSION: lur.u.version = lum->u.version; @@ -336,13 +333,57 @@ end: goto error; } } + /* + * We still have the memory map reference, and the fds have been + * sent to the sessiond. We can therefore close those fds. Note + * that we keep the write side of the wait_fd open, but close + * the read side. + */ + if (lur.ret_code == USTCOMM_OK) { + switch (lum->cmd) { + case LTTNG_UST_STREAM: + if (shm_fd >= 0) { + ret = close(shm_fd); + if (ret) { + PERROR("Error closing stream shm_fd"); + } + *args.stream.shm_fd = -1; + } + if (wait_fd >= 0) { + ret = close(wait_fd); + if (ret) { + PERROR("Error closing stream wait_fd"); + } + *args.stream.wait_fd = -1; + } + break; + case LTTNG_UST_METADATA: + case LTTNG_UST_CHANNEL: + if (shm_fd >= 0) { + ret = close(shm_fd); + if (ret) { + PERROR("Error closing channel shm_fd"); + } + *args.channel.shm_fd = -1; + } + if (wait_fd >= 0) { + ret = close(wait_fd); + if (ret) { + PERROR("Error closing channel wait_fd"); + } + *args.channel.wait_fd = -1; + } + break; + } + } + error: ust_unlock(); return ret; } static -void cleanup_sock_info(struct sock_info *sock_info) +void cleanup_sock_info(struct sock_info *sock_info, int exiting) { int ret; @@ -361,7 +402,13 @@ void cleanup_sock_info(struct sock_info *sock_info) sock_info->root_handle = -1; } sock_info->constructor_sem_posted = 0; - if (sock_info->wait_shm_mmap) { + /* + * wait_shm_mmap is used by listener threads outside of the + * ust lock, so we cannot tear it down ourselves, because we + * cannot join on these threads. Leave this task to the OS + * process exit. + */ + if (!exiting && sock_info->wait_shm_mmap) { ret = munmap(sock_info->wait_shm_mmap, sysconf(_SC_PAGE_SIZE)); if (ret) { ERR("Error unmapping wait shm"); @@ -413,7 +460,7 @@ int get_wait_shm(struct sock_info *sock_info, size_t mmap_size) * shared memory map will have been created. */ pid = wait(&status); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { wait_shm_fd = -1; goto end; } @@ -561,14 +608,15 @@ void wait_for_sessiond(struct sock_info *sock_info) if (ret < 0) { if (errno == EFAULT) { wait_poll_fallback = 1; - WARN( + DBG( "Linux kernels 2.6.33 to 3.0 (with the exception of stable versions) " "do not support FUTEX_WAKE on read-only memory mappings correctly. " "Please upgrade your kernel " "(fix is commit 9ea71503a8ed9184d2d0b8ccc4d269d05f7940ae in Linux kernel " "mainline). LTTng-UST will use polling mode fallback."); + if (ust_debug()) + PERROR("futex"); } - PERROR("futex"); } } return; @@ -834,10 +882,17 @@ void __attribute__((constructor)) lttng_ust_init(void) static void lttng_ust_cleanup(int exiting) { - cleanup_sock_info(&global_apps); + cleanup_sock_info(&global_apps, exiting); if (local_apps.allowed) { - cleanup_sock_info(&local_apps); + cleanup_sock_info(&local_apps, exiting); } + /* + * The teardown in this function all affect data structures + * accessed under the UST lock by the listener thread. This + * lock, along with the lttng_ust_comm_should_quit flag, ensure + * that none of these threads are accessing this data at this + * point. + */ lttng_ust_abi_exit(); lttng_ust_events_exit(); ltt_ring_buffer_client_discard_exit(); @@ -871,6 +926,7 @@ void __attribute__((destructor)) lttng_ust_exit(void) lttng_ust_comm_should_quit = 1; ust_unlock(); + /* cancel threads */ ret = pthread_cancel(global_apps.ust_listener); if (ret) { ERR("Error cancelling global ust listener thread"); @@ -881,6 +937,14 @@ void __attribute__((destructor)) lttng_ust_exit(void) ERR("Error cancelling local ust listener thread"); } } + /* + * Do NOT join threads: use of sys_futex makes it impossible to + * join the threads without using async-cancel, but async-cancel + * is delivered by a signal, which could hit the target thread + * anywhere in its code path, including while the ust_lock() is + * held, causing a deadlock for the other thread. Let the OS + * cleanup the threads if there are stalled in a syscall. + */ lttng_ust_cleanup(1); }