Make libustctl list only online pids v3
authorNils Carlson <nils.carlson@ericsson.com>
Mon, 16 May 2011 13:57:15 +0000 (15:57 +0200)
committerNils Carlson <nils.carlson@ericsson.com>
Tue, 17 May 2011 08:40:59 +0000 (10:40 +0200)
Changes since v2:
Botox.

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@ericsson.com>
Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
libust/tracectl.c
libustcomm/ustcomm.c
libustcomm/ustcomm.h
libustctl/libustctl.c

index bc0a07c046d26333f36ef1b19145f79c8ba53fa8..2f45d6be5d66fe249a197135e178755af33c597a 100644 (file)
@@ -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");
index ed6d8f121fea0069ac796ccd4162b81a80501746..3c7c0bb304c2599f0bfddf25a23be10ca61b4a44 100644 (file)
@@ -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,127 @@ 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;
+}
+
+#define MAX_SOCK_PATH_BASE_LEN 100
+
+static int ustcomm_get_sock_name(char *dir_name, pid_t pid, char *sock_name)
+{
+       struct dirent *dirent;
+       char sock_path_base[MAX_SOCK_PATH_BASE_LEN];
+       int len;
+       DIR *dir = opendir(dir_name);
+
+       snprintf(sock_path_base, MAX_SOCK_PATH_BASE_LEN - 1,
+                "%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 +683,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 +699,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 +714,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 +726,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;
index a91c111e8d7d02d1a1e69028f1e31b7f18744324..4706b72fbb930eaf4d22e5d1ac11702fe627171a 100644 (file)
@@ -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);
 
index 8b0dfc164c56bb9571a1202ed8f84d40ada3999b..4e6c495c6b744b5e8cb853a7309fbc0c6d908a44 100644 (file)
@@ -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)) {
This page took 0.028608 seconds and 4 git commands to generate.