[lttng-dev] [PATCH lttng-ust] Move wait_shm_mmap initialization to library constructor

Jonathan Rajotte jonathan.rajotte-julien at efficios.com
Fri Mar 8 10:01:12 EST 2019


Prevent us from deadlocking ourself if some glibc implementation
decide to hold the dl_load_* locks on fork operation.

This happens on Yocto Rocko and up when performing python tracing (import
lttngust). Why Yocto decided to patch glibc this way is a mystery
(ongoing effort) [1][2][3].

Anyhow, we can prevent this by moving the initialization of the
wait_shm_mmap to the library constructor since the dl_load_* locks are
nestable mutex.

Nothing in the git log for the wait_shm_mmap indicate a specific reason
to why it was done inside the listener thread. Doing it inside
wait_for_sessiond can help in some corner cases were /dev/shm
(or the shm path) files are unlinked. This is not much of an advantage.

[1] From yocto master branch: ee9db1a9152e8757ce4d831ff9f4472ff5a57dad
[2] From OE-Core: f2e586ebf59a9b7d5b216fc92aeb892069a4b0c1
[3] https://www.mail-archive.com/openembedded-core@lists.openembedded.org/msg101186.html

This was tested on a Yocto Rocko qemu x86-64 image with python agent
enabled.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien at efficios.com>
---
 liblttng-ust/lttng-ust-comm.c | 76 +++++++++++++++++++++++++++--------
 1 file changed, 60 insertions(+), 16 deletions(-)

diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c
index eab2d8eb..61dbb41b 100644
--- a/liblttng-ust/lttng-ust-comm.c
+++ b/liblttng-ust/lttng-ust-comm.c
@@ -264,7 +264,7 @@ struct sock_info global_apps = {
 	.global = 1,
 
 	.root_handle = -1,
-	.allowed = 1,
+	.allowed = 0,
 	.thread_active = 0,
 
 	.sock_path = LTTNG_DEFAULT_RUNDIR "/" LTTNG_UST_SOCK_FILENAME,
@@ -343,6 +343,8 @@ 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);
 
+static char *get_map_shm(struct sock_info *sock_info);
+
 ssize_t lttng_ust_read(int fd, void *buf, size_t len)
 {
 	ssize_t ret;
@@ -434,25 +436,48 @@ 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;
+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 +487,16 @@ 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;
+	}
+end:
+	return ret;
 }
 
 /*
@@ -1305,19 +1339,17 @@ 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))
@@ -1756,8 +1788,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 +1820,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 +1902,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
-- 
2.17.1



More information about the lttng-dev mailing list