From: Nils Carlson Date: Mon, 16 May 2011 13:57:15 +0000 (+0200) Subject: Make libustctl list only online pids v3 X-Git-Tag: v1.9.1~373 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=0f79e1ef1d4f31a91476f5a84e367f2c49ce4723;p=lttng-ust.git Make libustctl list only online pids v3 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/ 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 Acked-by: Mathieu Desnoyers --- diff --git a/libust/tracectl.c b/libust/tracectl.c index bc0a07c0..2f45d6be 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 ed6d8f12..3c7c0bb3 100644 --- a/libustcomm/ustcomm.c +++ b/libustcomm/ustcomm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/libustcomm/ustcomm.h b/libustcomm/ustcomm.h index a91c111e..4706b72f 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 8b0dfc16..4e6c495c 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)) {