#define _LGPL_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/prctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <usterr-signal-safe.h>
#include "tracepoint-internal.h"
#include "ltt-tracer-core.h"
+#include "compat.h"
#include "../libringbuffer/tlsfixup.h"
/*
*/
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.
*/
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)
{
* Disallow per-user tracing for setuid binaries.
*/
if (uid != geteuid()) {
- local_apps.allowed = 0;
+ assert(local_apps.allowed == 0);
return 0;
- } else {
- local_apps.allowed = 1;
}
home_dir = (const char *) getenv("HOME");
- if (!home_dir)
+ if (!home_dir) {
+ WARN("HOME environment variable not set. Disabling LTTng-UST per-user tracing.");
+ assert(local_apps.allowed == 0);
return -ENOENT;
+ }
+ local_apps.allowed = 1;
snprintf(local_apps.sock_path, PATH_MAX,
DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
snprintf(local_apps.wait_shm_path, PATH_MAX,
int register_app_to_sessiond(int socket)
{
ssize_t ret;
- int prctl_ret;
struct {
uint32_t major;
uint32_t minor;
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))
const struct lttng_ust_objd_ops *ops;
struct ustcomm_ust_reply lur;
int shm_fd, wait_fd;
+ char *shm_path, *wait_pipe_path;
union ust_args args;
ust_lock();
* Use lum.u output.
*/
lur.u.stream.memory_map_size = *args.stream.memory_map_size;
- shm_fd = *args.stream.shm_fd;
- wait_fd = *args.stream.wait_fd;
+ shm_fd = *args.stream.shm_fd;
+ shm_path = args.stream.shm_path;
+ wait_fd = *args.stream.wait_fd;
+ wait_pipe_path = args.stream.wait_pipe_path;
break;
case LTTNG_UST_METADATA:
case LTTNG_UST_CHANNEL:
lur.u.channel.memory_map_size = *args.channel.memory_map_size;
- shm_fd = *args.channel.shm_fd;
- wait_fd = *args.channel.wait_fd;
+ shm_fd = *args.channel.shm_fd;
+ shm_path = args.channel.shm_path;
+ wait_fd = *args.channel.wait_fd;
+ wait_pipe_path = args.channel.wait_pipe_path;
break;
case LTTNG_UST_TRACER_VERSION:
lur.u.version = lum->u.version;
&& lur.ret_code == USTCOMM_OK) {
int sendret = 0;
- /* we also need to send the file descriptors. */
- ret = ustcomm_send_fds_unix_sock(sock,
- &shm_fd, &shm_fd,
- 1, sizeof(int));
+ /* send the shm path */
+ ret = ustcomm_send_string(sock, shm_path, strlen(shm_path));
if (ret < 0) {
- perror("send shm_fd");
+ perror("send shm_path");
sendret = ret;
}
/*
* The sessiond expects 2 file descriptors, even upon
* error.
*/
- ret = ustcomm_send_fds_unix_sock(sock,
- &wait_fd, &wait_fd,
- 1, sizeof(int));
+ ret = ustcomm_send_string(sock, wait_pipe_path, strlen(wait_pipe_path));
if (ret < 0) {
- perror("send wait_fd");
+ perror("send wait_pipe_path");
goto error;
}
if (sendret) {
* 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;
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
*/
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;
}
{
struct timespec constructor_timeout;
sigset_t sig_all_blocked, orig_parent_mask;
+ pthread_attr_t thread_attr;
int timeout_mode;
int ret;
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
ret = setup_local_apps();
if (ret) {
- ERR("Error setting up to local apps");
+ DBG("local apps setup returned %d", ret);
}
/* A new thread created by pthread_create inherits the signal mask
sigfillset(&sig_all_blocked);
ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_parent_mask);
if (ret) {
- PERROR("pthread_sigmask: %s", strerror(ret));
+ ERR("pthread_sigmask: %s", strerror(ret));
}
- ret = pthread_create(&global_apps.ust_listener, NULL,
- ust_listener_thread, &global_apps);
+ 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(&local_apps.ust_listener, NULL,
+ 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) {
- PERROR("pthread_sigmask: %s", strerror(ret));
+ ERR("pthread_sigmask: %s", strerror(ret));
}
switch (timeout_mode) {
/* 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));
}
}
/*
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);
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 */
*/
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();