X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-comm.c;h=a464e88bfee2143e429273c646adabbf8aaa61bb;hb=6ddc916dfa930b6b9018ffd53a76faeb61b81ebd;hp=0765c9b538a6a9370570647fea6780fe49070705;hpb=50be2fc41b02ee04860b5199d0ce2d346b1ea7c2;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 0765c9b5..a464e88b 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "tracepoint-internal.h" #include "ltt-tracer-core.h" #include "compat.h" @@ -78,6 +79,12 @@ static sem_t constructor_wait; */ static int sem_count = { 2 }; +/* + * Counting nesting within lttng-ust. Used to ensure that calling fork() + * from liblttng-ust does not execute the pre/post fork handlers. + */ +static int __thread lttng_ust_nest_count; + /* * Info about socket and associated listener thread. */ @@ -130,6 +137,15 @@ extern void ltt_ring_buffer_client_overwrite_exit(void); extern void ltt_ring_buffer_client_discard_exit(void); extern void ltt_ring_buffer_metadata_client_exit(void); +/* + * Force a read (imply TLS fixup for dlopen) of TLS variables. + */ +static +void lttng_fixup_nest_count_tls(void) +{ + asm volatile ("" : : "m" (lttng_ust_nest_count)); +} + static int setup_local_apps(void) { @@ -236,6 +252,7 @@ int handle_message(struct sock_info *sock_info, struct ustcomm_ust_reply lur; int shm_fd, wait_fd; union ust_args args; + ssize_t len; ust_lock(); @@ -265,6 +282,74 @@ int handle_message(struct sock_info *sock_info, else ret = lttng_ust_objd_unref(lum->handle); break; + case LTTNG_UST_FILTER: + { + /* Receive filter data */ + struct lttng_ust_filter_bytecode *bytecode; + + if (lum->u.filter.data_size > FILTER_BYTECODE_MAX_LEN) { + ERR("Filter data size is too large: %u bytes\n", + lum->u.filter.data_size); + ret = -EINVAL; + goto error; + } + + if (lum->u.filter.reloc_offset > lum->u.filter.data_size - 1) { + ERR("Filter reloc offset %u is not within data\n", + 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->data, + lum->u.filter.data_size); + switch (len) { + case 0: /* orderly shutdown */ + ret = 0; + free(bytecode); + goto error; + case -1: + DBG("Receive failed from lttng-sessiond with errno %d", errno); + if (errno == ECONNRESET) { + ERR("%s remote end closed connection\n", sock_info->name); + ret = -EINVAL; + free(bytecode); + goto error; + } + ret = -EINVAL; + goto end; + default: + if (len == lum->u.filter.data_size) { + DBG("filter data received\n"); + break; + } else { + ERR("incorrect filter data message size: %zd\n", len); + ret = -EINVAL; + free(bytecode); + goto end; + } + } + bytecode->len = lum->u.filter.data_size; + bytecode->reloc_offset = lum->u.filter.reloc_offset; + if (ops->cmd) { + ret = ops->cmd(lum->handle, lum->cmd, + (unsigned long) bytecode, + &args); + if (ret) { + free(bytecode); + } + /* don't free bytecode if everything went fine. */ + } else { + ret = -ENOSYS; + free(bytecode); + } + break; + } default: if (ops->cmd) ret = ops->cmd(lum->handle, lum->cmd, @@ -346,6 +431,22 @@ end: goto error; } } + /* + * LTTNG_UST_TRACEPOINT_FIELD_LIST_GET needs to send the field + * after the reply. + */ + if (lur.ret_code == USTCOMM_OK) { + switch (lum->cmd) { + case LTTNG_UST_TRACEPOINT_FIELD_LIST_GET: + len = ustcomm_send_unix_sock(sock, + &args.field_list.entry, + sizeof(args.field_list.entry)); + if (len != sizeof(args.field_list.entry)) { + ret = -1; + 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 @@ -464,7 +565,9 @@ int get_wait_shm(struct sock_info *sock_info, size_t mmap_size) * If the open failed because the file did not exist, try * creating it ourself. */ + lttng_ust_nest_count++; pid = fork(); + lttng_ust_nest_count--; if (pid > 0) { int status; @@ -513,9 +616,9 @@ int get_wait_shm(struct sock_info *sock_info, size_t mmap_size) ret = ftruncate(wait_shm_fd, mmap_size); if (ret) { PERROR("ftruncate"); - exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } - exit(EXIT_SUCCESS); + _exit(EXIT_SUCCESS); } /* * For local shm, we need to have rw access to accept @@ -527,13 +630,13 @@ int get_wait_shm(struct sock_info *sock_info, size_t mmap_size) */ if (!sock_info->global && errno != EACCES) { ERR("Error opening shm %s", sock_info->wait_shm_path); - exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } /* * The shm exists, but we cannot open it RW. Report * success. */ - exit(EXIT_SUCCESS); + _exit(EXIT_SUCCESS); } else { return -1; } @@ -647,7 +750,7 @@ error: * This thread does not allocate any resource, except within * handle_message, within mutex protection. This mutex protects against * fork and exit. - * The other moment it allocates resources is at socket connexion, which + * The other moment it allocates resources is at socket connection, which * is also protected by the mutex. */ static @@ -832,6 +935,8 @@ int get_timeout(struct timespec *constructor_timeout) void __attribute__((constructor)) lttng_ust_init(void) { struct timespec constructor_timeout; + sigset_t sig_all_blocked, orig_parent_mask; + pthread_attr_t thread_attr; int timeout_mode; int ret; @@ -846,6 +951,7 @@ void __attribute__((constructor)) lttng_ust_init(void) lttng_fixup_event_tls(); lttng_fixup_ringbuffer_tls(); lttng_fixup_vtid_tls(); + lttng_fixup_nest_count_tls(); /* * We want precise control over the order in which we construct @@ -868,15 +974,51 @@ void __attribute__((constructor)) lttng_ust_init(void) if (ret) { ERR("Error setting up to local apps"); } - ret = pthread_create(&local_apps.ust_listener, NULL, - ust_listener_thread, &local_apps); + /* A new thread created by pthread_create inherits the signal mask + * from the parent. To avoid any signal being received by the + * listener thread, we block all signals temporarily in the parent, + * while we create the listener thread. + */ + sigfillset(&sig_all_blocked); + ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_parent_mask); + if (ret) { + ERR("pthread_sigmask: %s", strerror(ret)); + } + + ret = pthread_attr_init(&thread_attr); + if (ret) { + ERR("pthread_attr_init: %s", strerror(ret)); + } + ret = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + if (ret) { + ERR("pthread_attr_setdetachstate: %s", strerror(ret)); + } + + ret = pthread_create(&global_apps.ust_listener, &thread_attr, + ust_listener_thread, &global_apps); + if (ret) { + ERR("pthread_create global: %s", strerror(ret)); + } if (local_apps.allowed) { - ret = pthread_create(&global_apps.ust_listener, NULL, - ust_listener_thread, &global_apps); + ret = pthread_create(&local_apps.ust_listener, &thread_attr, + ust_listener_thread, &local_apps); + if (ret) { + ERR("pthread_create local: %s", strerror(ret)); + } } else { handle_register_done(&local_apps); } + ret = pthread_attr_destroy(&thread_attr); + if (ret) { + ERR("pthread_attr_destroy: %s", strerror(ret)); + } + + /* Restore original signal mask in parent */ + ret = pthread_sigmask(SIG_SETMASK, &orig_parent_mask, NULL); + if (ret) { + ERR("pthread_sigmask: %s", strerror(ret)); + } switch (timeout_mode) { case 1: /* timeout wait */ @@ -951,12 +1093,14 @@ void __attribute__((destructor)) lttng_ust_exit(void) /* cancel threads */ ret = pthread_cancel(global_apps.ust_listener); if (ret) { - ERR("Error cancelling global ust listener thread"); + ERR("Error cancelling global ust listener thread: %s", + strerror(ret)); } if (local_apps.allowed) { ret = pthread_cancel(local_apps.ust_listener); if (ret) { - ERR("Error cancelling local ust listener thread"); + ERR("Error cancelling local ust listener thread: %s", + strerror(ret)); } } /* @@ -988,6 +1132,8 @@ void ust_before_fork(sigset_t *save_sigset) sigset_t all_sigs; int ret; + if (lttng_ust_nest_count) + return; /* Disable signals */ sigfillset(&all_sigs); ret = sigprocmask(SIG_BLOCK, &all_sigs, save_sigset); @@ -1013,6 +1159,8 @@ static void ust_after_fork_common(sigset_t *restore_sigset) void ust_after_fork_parent(sigset_t *restore_sigset) { + if (lttng_ust_nest_count) + return; DBG("process %d", getpid()); rcu_bp_after_fork_parent(); /* Release mutexes and reenable signals */ @@ -1030,6 +1178,8 @@ void ust_after_fork_parent(sigset_t *restore_sigset) */ void ust_after_fork_child(sigset_t *restore_sigset) { + if (lttng_ust_nest_count) + return; DBG("process %d", getpid()); /* Release urcu mutexes */ rcu_bp_after_fork_child();