[lttng-dev] [PATCH lttng-tools 6/6] Fix: Set thread stack size to ulimit soft value

Michael Jeanson mjeanson at efficios.com
Wed Jun 15 21:18:07 UTC 2016


Some libc don't honor the limit set for the stack size and use their own
empirically chosen static value. Detect this behavior by checking if the
current stack size is smally than the soft limit and in that case set
the pthread stack size to soft limit value.

Signed-off-by: Michael Jeanson <mjeanson at efficios.com>
---
 src/bin/lttng-consumerd/lttng-consumerd.c | 17 +++++---
 src/bin/lttng-relayd/live.c               | 10 ++---
 src/bin/lttng-relayd/live.h               |  2 +-
 src/bin/lttng-relayd/main.c               | 14 ++++---
 src/bin/lttng-sessiond/main.c             | 27 +++++++------
 src/common/utils.c                        | 64 +++++++++++++++++++++++++++++++
 src/common/utils.h                        |  1 +
 7 files changed, 107 insertions(+), 28 deletions(-)

diff --git a/src/bin/lttng-consumerd/lttng-consumerd.c b/src/bin/lttng-consumerd/lttng-consumerd.c
index 00660fc..2f1d01c 100644
--- a/src/bin/lttng-consumerd/lttng-consumerd.c
+++ b/src/bin/lttng-consumerd/lttng-consumerd.c
@@ -57,6 +57,8 @@
 static pthread_t channel_thread, data_thread, metadata_thread,
 		sessiond_thread, metadata_timer_thread, health_thread;
 
+static pthread_attr_t *tattr;
+
 /* to count the number of times the user pressed ctrl+c */
 static int sigintcount = 0;
 
@@ -351,6 +353,9 @@ int main(int argc, char **argv)
 		}
 	}
 
+	/* Get stacksize limit */
+	tattr = get_pthread_attr_stacksize();
+
 	/*
 	 * Starting from here, we can create threads. This needs to be after
 	 * lttng_daemonize due to RCU.
@@ -498,7 +503,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage the client socket */
-	ret = pthread_create(&health_thread, NULL,
+	ret = pthread_create(&health_thread, tattr,
 			thread_manage_health, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -517,7 +522,7 @@ int main(int argc, char **argv)
 	cmm_smp_mb();	/* Read ready before following operations */
 
 	/* Create thread to manage channels */
-	ret = pthread_create(&channel_thread, NULL,
+	ret = pthread_create(&channel_thread, tattr,
 			consumer_thread_channel_poll,
 			(void *) ctx);
 	if (ret) {
@@ -528,7 +533,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage the polling/writing of trace metadata */
-	ret = pthread_create(&metadata_thread, NULL,
+	ret = pthread_create(&metadata_thread, tattr,
 			consumer_thread_metadata_poll,
 			(void *) ctx);
 	if (ret) {
@@ -539,7 +544,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage the polling/writing of trace data */
-	ret = pthread_create(&data_thread, NULL, consumer_thread_data_poll,
+	ret = pthread_create(&data_thread, tattr, consumer_thread_data_poll,
 			(void *) ctx);
 	if (ret) {
 		errno = ret;
@@ -549,7 +554,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create the thread to manage the receive of fd */
-	ret = pthread_create(&sessiond_thread, NULL,
+	ret = pthread_create(&sessiond_thread, tattr,
 			consumer_thread_sessiond_poll,
 			(void *) ctx);
 	if (ret) {
@@ -563,7 +568,7 @@ int main(int argc, char **argv)
 	 * Create the thread to manage the UST metadata periodic timer and
 	 * live timer.
 	 */
-	ret = pthread_create(&metadata_timer_thread, NULL,
+	ret = pthread_create(&metadata_timer_thread, tattr,
 			consumer_timer_thread, (void *) ctx);
 	if (ret) {
 		errno = ret;
diff --git a/src/bin/lttng-relayd/live.c b/src/bin/lttng-relayd/live.c
index e2096ec..32efab1 100644
--- a/src/bin/lttng-relayd/live.c
+++ b/src/bin/lttng-relayd/live.c
@@ -2147,13 +2147,13 @@ int relayd_live_join(void)
 /*
  * main
  */
-int relayd_live_create(struct lttng_uri *uri)
+int relayd_live_create(struct lttng_uri *uri, const pthread_attr_t *tattr)
 {
 	int ret = 0, retval = 0;
 	void *status;
 	int is_root;
 
-	if (!uri) {
+	if (!uri || !tattr) {
 		retval = -1;
 		goto exit_init_data;
 	}
@@ -2186,7 +2186,7 @@ int relayd_live_create(struct lttng_uri *uri)
 	}
 
 	/* Setup the dispatcher thread */
-	ret = pthread_create(&live_dispatcher_thread, NULL,
+	ret = pthread_create(&live_dispatcher_thread, tattr,
 			thread_dispatcher, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -2196,7 +2196,7 @@ int relayd_live_create(struct lttng_uri *uri)
 	}
 
 	/* Setup the worker thread */
-	ret = pthread_create(&live_worker_thread, NULL,
+	ret = pthread_create(&live_worker_thread, tattr,
 			thread_worker, NULL);
 	if (ret) {
 		errno = ret;
@@ -2206,7 +2206,7 @@ int relayd_live_create(struct lttng_uri *uri)
 	}
 
 	/* Setup the listener thread */
-	ret = pthread_create(&live_listener_thread, NULL,
+	ret = pthread_create(&live_listener_thread, tattr,
 			thread_listener, (void *) NULL);
 	if (ret) {
 		errno = ret;
diff --git a/src/bin/lttng-relayd/live.h b/src/bin/lttng-relayd/live.h
index 2b8a3a0..6cd85e9 100644
--- a/src/bin/lttng-relayd/live.h
+++ b/src/bin/lttng-relayd/live.h
@@ -24,7 +24,7 @@
 
 #include "lttng-relayd.h"
 
-int relayd_live_create(struct lttng_uri *live_uri);
+int relayd_live_create(struct lttng_uri *live_uri, const pthread_attr_t *tattr);
 int relayd_live_stop(void);
 int relayd_live_join(void);
 
diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c
index 6ad6566..505e884 100644
--- a/src/bin/lttng-relayd/main.c
+++ b/src/bin/lttng-relayd/main.c
@@ -119,6 +119,8 @@ static pthread_t dispatcher_thread;
 static pthread_t worker_thread;
 static pthread_t health_thread;
 
+static pthread_attr_t *tattr;
+
 /*
  * last_relay_stream_id_lock protects last_relay_stream_id increment
  * atomicity on 32-bit architectures.
@@ -2778,6 +2780,8 @@ int main(int argc, char **argv)
 		}
 	}
 
+	/* Get stack size limit */
+	tattr = get_pthread_attr_stacksize();
 
 	/* Initialize thread health monitoring */
 	health_relayd = health_app_create(NR_HEALTH_RELAYD_TYPES);
@@ -2840,7 +2844,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage the client socket */
-	ret = pthread_create(&health_thread, NULL,
+	ret = pthread_create(&health_thread, tattr,
 			thread_manage_health, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -2850,7 +2854,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Setup the dispatcher thread */
-	ret = pthread_create(&dispatcher_thread, NULL,
+	ret = pthread_create(&dispatcher_thread, tattr,
 			relay_thread_dispatcher, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -2860,7 +2864,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Setup the worker thread */
-	ret = pthread_create(&worker_thread, NULL,
+	ret = pthread_create(&worker_thread, tattr,
 			relay_thread_worker, NULL);
 	if (ret) {
 		errno = ret;
@@ -2870,7 +2874,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Setup the listener thread */
-	ret = pthread_create(&listener_thread, NULL,
+	ret = pthread_create(&listener_thread, tattr,
 			relay_thread_listener, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -2879,7 +2883,7 @@ int main(int argc, char **argv)
 		goto exit_listener_thread;
 	}
 
-	ret = relayd_live_create(live_uri);
+	ret = relayd_live_create(live_uri, tattr);
 	if (ret) {
 		ERR("Starting live viewer threads");
 		retval = -1;
diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c
index bab92a4..359cb83 100644
--- a/src/bin/lttng-sessiond/main.c
+++ b/src/bin/lttng-sessiond/main.c
@@ -212,6 +212,8 @@ static pthread_t ht_cleanup_thread;
 static pthread_t agent_reg_thread;
 static pthread_t load_session_thread;
 
+static pthread_attr_t *tattr;
+
 /*
  * UST registration command queue. This queue is tied with a futex and uses a N
  * wakers / 1 waiter implemented and detailed in futex.c/.h
@@ -2407,7 +2409,7 @@ static int spawn_consumer_thread(struct consumer_data *consumer_data)
 		goto error;
 	}
 
-	ret = pthread_create(&consumer_data->thread, NULL, thread_manage_consumer,
+	ret = pthread_create(&consumer_data->thread, tattr, thread_manage_consumer,
 			consumer_data);
 	if (ret) {
 		errno = ret;
@@ -5636,6 +5638,9 @@ int main(int argc, char **argv)
 		goto exit_create_run_as_worker_cleanup;
 	}
 
+	/* Get stack size limit */
+	tattr = get_pthread_attr_stacksize();
+
 	/*
 	 * Starting from here, we can create threads. This needs to be after
 	 * lttng_daemonize due to RCU.
@@ -5670,7 +5675,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to clean up RCU hash tables */
-	ret = pthread_create(&ht_cleanup_thread, NULL,
+	ret = pthread_create(&ht_cleanup_thread, tattr,
 			thread_ht_cleanup, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6042,7 +6047,7 @@ int main(int argc, char **argv)
 	load_info->path = opt_load_session_path;
 
 	/* Create health-check thread */
-	ret = pthread_create(&health_thread, NULL,
+	ret = pthread_create(&health_thread, tattr,
 			thread_manage_health, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6052,7 +6057,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage the client socket */
-	ret = pthread_create(&client_thread, NULL,
+	ret = pthread_create(&client_thread, tattr,
 			thread_manage_clients, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6062,7 +6067,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to dispatch registration */
-	ret = pthread_create(&dispatch_thread, NULL,
+	ret = pthread_create(&dispatch_thread, tattr,
 			thread_dispatch_ust_registration, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6072,7 +6077,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage application registration. */
-	ret = pthread_create(&reg_apps_thread, NULL,
+	ret = pthread_create(&reg_apps_thread, tattr,
 			thread_registration_apps, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6082,7 +6087,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage application socket */
-	ret = pthread_create(&apps_thread, NULL,
+	ret = pthread_create(&apps_thread, tattr,
 			thread_manage_apps, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6092,7 +6097,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create thread to manage application notify socket */
-	ret = pthread_create(&apps_notify_thread, NULL,
+	ret = pthread_create(&apps_notify_thread, tattr,
 			ust_thread_manage_notify, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6102,7 +6107,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create agent registration thread. */
-	ret = pthread_create(&agent_reg_thread, NULL,
+	ret = pthread_create(&agent_reg_thread, tattr,
 			agent_thread_manage_registration, (void *) NULL);
 	if (ret) {
 		errno = ret;
@@ -6114,7 +6119,7 @@ int main(int argc, char **argv)
 	/* Don't start this thread if kernel tracing is not requested nor root */
 	if (is_root && !opt_no_kernel) {
 		/* Create kernel thread to manage kernel event */
-		ret = pthread_create(&kernel_thread, NULL,
+		ret = pthread_create(&kernel_thread, tattr,
 				thread_manage_kernel, (void *) NULL);
 		if (ret) {
 			errno = ret;
@@ -6125,7 +6130,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Create session loading thread. */
-	ret = pthread_create(&load_session_thread, NULL, thread_load_session,
+	ret = pthread_create(&load_session_thread, tattr, thread_load_session,
 			load_info);
 	if (ret) {
 		errno = ret;
diff --git a/src/common/utils.c b/src/common/utils.c
index 1e52ae0..62f970c 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -31,6 +31,8 @@
 #include <pwd.h>
 #include <sys/file.h>
 #include <unistd.h>
+#include <stdbool.h>
+#include <sys/resource.h>
 
 #include <common/common.h>
 #include <common/runas.h>
@@ -1383,3 +1385,65 @@ int utils_show_man_page(int section, const char *page_name)
 		section_string, page_name, NULL);
 	return ret;
 }
+
+static bool pthread_ss_done = false;
+static pthread_attr_t *tattr = NULL;
+static pthread_attr_t tattr_value;
+
+/*
+ * Some libc don't honor the limit set for the stack size and use their own
+ * empirically chosen static value. This function checks if the current stack
+ * size is smaller than the stack size limit and if so returns a
+ * pthread_attr_t struct where the thread stack size is set to the soft stack
+ * size limit.
+ *
+ * If the libc honors stack size limit, return a NULL pointer.
+ */
+LTTNG_HIDDEN
+pthread_attr_t *get_pthread_attr_stacksize() {
+	int ret = 0;
+	size_t ptstacksize;
+	struct rlimit rlim;
+
+	/* Return cached value */
+	if (pthread_ss_done) {
+		goto end;
+	}
+
+	/* Get stack size limits */
+	ret = getrlimit(RLIMIT_STACK, &rlim);
+	if (ret < 0) {
+		PERROR("getrlimit");
+		goto end;
+	}
+	DBG("Stack size limits: soft %lld, hard %lld bytes",
+			(long long) rlim.rlim_cur,
+			(long long) rlim.rlim_max);
+
+	/* Get default thread stack size */
+	ret = pthread_attr_getstacksize(&tattr_value, &ptstacksize);
+	if (ret < 0) {
+		PERROR("pthread_attr_getstacksize");
+		goto end;
+	}
+	DBG("Default pthread stack size is %zu bytes", ptstacksize);
+
+	/* Check if default thread stack size respects ulimits */
+	if (ptstacksize < rlim.rlim_cur) {
+		MSG("Your libc doesn't honor stack size limits, setting thread stack size to soft limit (%lld bytes)",
+				(long long) rlim.rlim_cur);
+
+		/* Create pthread_attr_t struct with ulimit stack size */
+		ret = pthread_attr_setstacksize(&tattr_value, rlim.rlim_cur);
+		if (ret < 0) {
+			PERROR("pthread_attr_setstacksize");
+			goto end;
+		}
+		tattr = &tattr_value;
+	}
+
+	/* Enable cached value */
+	pthread_ss_done = true;
+end:
+	return tattr;
+}
diff --git a/src/common/utils.h b/src/common/utils.h
index 7285f5c..568c123 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -60,5 +60,6 @@ int utils_create_lock_file(const char *filepath);
 int utils_recursive_rmdir(const char *path);
 int utils_truncate_stream_file(int fd, off_t length);
 int utils_show_man_page(int section, const char *page_name);
+pthread_attr_t *get_pthread_attr_stacksize();
 
 #endif /* _COMMON_UTILS_H */
-- 
2.7.4



More information about the lttng-dev mailing list