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

Nils Carlson nils.carlson at ericsson.com
Mon May 16 10:38:49 EDT 2011


On 05/16/2011 04:23 PM, Mathieu Desnoyers wrote:
> * Nils Carlson (nils.carlson at ericsson.com) wrote:
>> 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.
>
> Hi Nils,
>
> I'm OK with the approach. I have a few cosmetic comments below,
>
>>
>> Signed-off-by: Nils Carlson<nils.carlson at ericsson.com>
>> ---
>>   libust/tracectl.c     |    9 +++-
>>   libustcomm/ustcomm.c  |  150 ++++++++++++++++++++++++++++++++++++++++++++-----
>>   libustcomm/ustcomm.h  |    7 ++
>>   libustctl/libustctl.c |   18 +-----
>>   4 files changed, 153 insertions(+), 31 deletions(-)
>>
>> diff --git a/libust/tracectl.c b/libust/tracectl.c
>> index bc0a07c..fb9130c 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..17bd9d9 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,125 @@ 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) {
>
> Errno is a TLS variable, while the value returned by strtoul is directly
> accessible from registers. So I would tend to think that using errno all
> the time will bloat our code, causing TLS accesses when not necessary.
> And I fear that on systems lacking TLS support (such as Android), they
> might simply use a shared variable modified concurrently across threads,
> which could be racy. So I would prefer to use the return value of the
> functions to trigger the error, and use the errno value only to print
> the error message in more details. Otherwise, I'm worried that we might
> end up either missing errors or triggering on a false-positive from the
> wrong thread.
Please read the man page for strtoul. Functions such as this one don't 
return anything to indicate errors, errno is the only way to check.

>
>> +		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 + 1];
>> +
>> +	if (snprintf(proc_name, PATH_MAX, "/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) {
>
> Please use: (unsigned long) time_from_pid  (with the space) (typical in
> kernel coding style, which we try to follow).

Done, though as usual this isn't consistent with already existing code.
>
>> +		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)) {
>> +			printf("found %s\n", dirent->d_name);
>
> Should this message be only printed in verbose mode ?

Darn, debug! :-) Will fix the rest.

/Nils




More information about the lttng-dev mailing list