[ltt-dev] [UST PATCH] Make libustctl list only online pids v2

Nils Carlson nils.carlson at ericsson.com
Mon May 16 11:21:39 EDT 2011


Changes since v1:
Cosmetic surgery at a european cost

Previously libustctl would list all pids. This patch changes this
so only online pids are listed. This is done by appending on each
socket name the mtime from the proc/<pid> directory. This way a
socket can be checked to see if the appended mtime matches the
mtime of the proc dir for the current pid, thus allowing us to
distinguish between old and new socket files.

Signed-off-by: Nils Carlson <nils.carlson at ericsson.com>
---
 libust/tracectl.c     |    9 +++-
 libustcomm/ustcomm.c  |  148 ++++++++++++++++++++++++++++++++++++++++++++-----
 libustcomm/ustcomm.h  |    7 ++
 libustctl/libustctl.c |   18 +-----
 4 files changed, 151 insertions(+), 31 deletions(-)

diff --git a/libust/tracectl.c b/libust/tracectl.c
index bc0a07c..2f45d6b 100644
--- a/libust/tracectl.c
+++ b/libust/tracectl.c
@@ -1228,12 +1228,19 @@ static struct ustcomm_sock * init_app_socket(int epoll_fd)
 	char *dir_name, *sock_name;
 	int result;
 	struct ustcomm_sock *sock = NULL;
+	time_t mtime;
 
 	dir_name = ustcomm_user_sock_dir();
 	if (!dir_name)
 		return NULL;
 
-	result = asprintf(&sock_name, "%s/%d", dir_name, (int)getpid());
+	mtime = ustcomm_pid_st_mtime(getpid());
+	if (!mtime) {
+		goto free_dir_name;
+	}
+
+	result = asprintf(&sock_name, "%s/%d.%ld", dir_name,
+			  (int) getpid(), (long) mtime);
 	if (result < 0) {
 		ERR("string overflow allocating socket name, "
 		    "UST thread bailing");
diff --git a/libustcomm/ustcomm.c b/libustcomm/ustcomm.c
index ed6d8f1..e8d8a93 100644
--- a/libustcomm/ustcomm.c
+++ b/libustcomm/ustcomm.c
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 #include <signal.h>
 #include <errno.h>
+#include <limits.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <unistd.h>
@@ -550,6 +551,124 @@ char *ustcomm_user_sock_dir(void)
 	return sock_dir;
 }
 
+static int time_and_pid_from_socket_name(char *sock_name, unsigned long *time,
+					 pid_t *pid)
+{
+	char *saveptr, *pid_m_time_str;
+	char *sock_basename = strdup(basename(sock_name));
+
+	if (!sock_basename) {
+		return -1;
+	}
+
+	/* This is the pid */
+	pid_m_time_str = strtok_r(sock_basename, ".", &saveptr);
+	if (!pid_m_time_str) {
+		goto out_err;
+	}
+
+	errno = 0;
+	*pid = (pid_t)strtoul(pid_m_time_str, NULL, 10);
+	if (errno) {
+		goto out_err;
+	}
+
+	/* This should be the time-stamp */
+	pid_m_time_str = strtok_r(NULL, ".", &saveptr);
+	if (!pid_m_time_str) {
+		goto out_err;
+	}
+
+	errno = 0;
+	*time = strtoul(pid_m_time_str, NULL, 10);
+	if (errno) {
+		goto out_err;
+	}
+
+	return 0;
+
+out_err:
+	free(sock_basename);
+	return -1;
+}
+
+time_t ustcomm_pid_st_mtime(pid_t pid)
+{
+	struct stat proc_stat;
+	char proc_name[PATH_MAX];
+
+	if (snprintf(proc_name, PATH_MAX - 1, "/proc/%ld", (long) pid) < 0) {
+		return 0;
+	}
+
+	if (stat(proc_name, &proc_stat)) {
+		return 0;
+	}
+
+	return proc_stat.st_mtime;
+}
+
+int ustcomm_is_socket_live(char *sock_name, pid_t *read_pid)
+{
+	time_t time_from_pid;
+	unsigned long time_from_sock;
+	pid_t pid;
+
+	if (time_and_pid_from_socket_name(sock_name, &time_from_sock, &pid)) {
+		return 0;
+	}
+
+	if (read_pid) {
+		*read_pid = pid;
+	}
+
+	time_from_pid = ustcomm_pid_st_mtime(pid);
+	if (!time_from_pid) {
+		return 0;
+	}
+
+	if ((unsigned long) time_from_pid == time_from_sock) {
+		return 1;
+	}
+
+	return 0;
+}
+
+static int ustcomm_get_sock_name(char *dir_name, pid_t pid, char *sock_name)
+{
+	struct dirent *dirent;
+	char sock_path_base[101];
+	int len;
+	DIR *dir = opendir(dir_name);
+
+	snprintf(sock_path_base, 100, "%ld.", (long) pid);
+	len = strlen(sock_path_base);
+
+	while ((dirent = readdir(dir))) {
+		if (!strcmp(dirent->d_name, ".") ||
+		    !strcmp(dirent->d_name, "..") ||
+		    !strcmp(dirent->d_name, "ust-consumer") ||
+		    dirent->d_type == DT_DIR ||
+		    strncmp(dirent->d_name, sock_path_base, len)) {
+			continue;
+		}
+
+		if (ustcomm_is_socket_live(dirent->d_name, NULL)) {
+			if (snprintf(sock_name, PATH_MAX - 1, "%s/%s",
+				     dir_name, dirent->d_name) < 0) {
+				PERROR("path longer than PATH_MAX?");
+				goto out_err;
+			}
+			closedir(dir);
+			return 0;
+		}
+	}
+
+out_err:
+	closedir(dir);
+	return -1;
+}
+
 /* Open a connection to a traceable app.
  *
  * Return value:
@@ -561,16 +680,15 @@ static int connect_app_non_root(pid_t pid, int *app_fd)
 {
 	int result;
 	int retval = 0;
-	char *dir_name, *sock_name;
+	char *dir_name;
+	char sock_name[PATH_MAX];
 
 	dir_name = ustcomm_user_sock_dir();
 	if (!dir_name)
 		return -ENOMEM;
 
-	result = asprintf(&sock_name, "%s/%d", dir_name, pid);
-	if (result < 0) {
-		ERR("failed to allocate socket name");
-		retval = -1;
+	if (ustcomm_get_sock_name(dir_name, pid, sock_name)) {
+		retval = -ENOENT;
 		goto free_dir_name;
 	}
 
@@ -578,11 +696,9 @@ static int connect_app_non_root(pid_t pid, int *app_fd)
 	if (result < 0) {
 		ERR("failed to connect to app");
 		retval = -1;
-		goto free_sock_name;
+		goto free_dir_name;
 	}
 
-free_sock_name:
-	free(sock_name);
 free_dir_name:
 	free(dir_name);
 
@@ -595,8 +711,8 @@ static int connect_app_root(pid_t pid, int *app_fd)
 {
 	DIR *tmp_dir;
 	struct dirent *dirent;
-	char *sock_name;
-	int result;
+	char dir_name[PATH_MAX], sock_name[PATH_MAX];
+	int result = -1;
 
 	tmp_dir = opendir(USER_TMP_DIR);
 	if (!tmp_dir) {
@@ -607,14 +723,16 @@ static int connect_app_root(pid_t pid, int *app_fd)
 		if (!strncmp(dirent->d_name, USER_SOCK_DIR_BASE,
 			     strlen(USER_SOCK_DIR_BASE))) {
 
-			if (asprintf(&sock_name, USER_TMP_DIR "/%s/%u",
-				     dirent->d_name, pid) < 0) {
-				goto close_tmp_dir;
+			if (snprintf(dir_name, PATH_MAX - 1, "%s/%s", USER_TMP_DIR,
+				     dirent->d_name) < 0) {
+				continue;
 			}
 
-			result = ustcomm_connect_path(sock_name, app_fd);
+			if (ustcomm_get_sock_name(dir_name, pid, sock_name)) {
+				continue;
+			}
 
-			free(sock_name);
+			result = ustcomm_connect_path(sock_name, app_fd);
 
 			if (result == 0) {
 				goto close_tmp_dir;
diff --git a/libustcomm/ustcomm.h b/libustcomm/ustcomm.h
index a91c111..4706b72 100644
--- a/libustcomm/ustcomm.h
+++ b/libustcomm/ustcomm.h
@@ -162,6 +162,13 @@ extern int ustcomm_request_consumer(pid_t pid, const char *channel);
 
 /* Returns the current users socket directory, must be freed */
 extern char *ustcomm_user_sock_dir(void);
+
+/* Get the st_m_time from proc*/
+extern time_t ustcomm_pid_st_mtime(pid_t pid);
+
+/* Check that a socket is live */
+extern int ustcomm_is_socket_live(char *sock_name, pid_t *read_pid);
+
 extern int ustcomm_connect_app(pid_t pid, int *app_fd);
 extern int ustcomm_connect_path(const char *path, int *connection_fd);
 
diff --git a/libustctl/libustctl.c b/libustctl/libustctl.c
index 8b0dfc1..4e6c495 100644
--- a/libustctl/libustctl.c
+++ b/libustctl/libustctl.c
@@ -110,7 +110,7 @@ static int get_pids_in_dir(DIR *dir, pid_t **pid_list,
 			    unsigned int *pid_list_size)
 {
 	struct dirent *dirent;
-	long read_pid;
+	pid_t read_pid;
 
 	while ((dirent = readdir(dir))) {
 		if (!strcmp(dirent->d_name, ".") ||
@@ -121,21 +121,9 @@ static int get_pids_in_dir(DIR *dir, pid_t **pid_list,
 			continue;
 		}
 
-		errno = 0;
-		read_pid = strtol(dirent->d_name, NULL, 10);
-		if (errno) {
-			continue;
-		}
-
-		/*
-		 * FIXME: Here we previously called pid_is_online, which
-		 * always returned 1, now I replaced it with just 1.
-		 * We need to figure out an intelligent way of solving
-		 * this, maybe connect-disconnect.
-		 */
-		if (1) {
+		if (ustcomm_is_socket_live(dirent->d_name, &read_pid)) {
 
-			(*pid_list)[(*pid_list_index)++] = read_pid;
+			(*pid_list)[(*pid_list_index)++] = (long) read_pid;
 
 			if (*pid_list_index == *pid_list_size) {
 				if (realloc_pid_list(pid_list, pid_list_size)) {
-- 
1.7.2.5





More information about the lttng-dev mailing list