[lttng-dev] [PATCH lttng-ust] Fix: Make deadlocks with baddr statedump unlikely

Mathieu Desnoyers mathieu.desnoyers at efficios.com
Mon Mar 17 10:24:01 EDT 2014


----- Original Message -----
> From: "Paul Woegerer" <paul_woegerer at mentor.com>
> To: lttng-dev at lists.lttng.org, "mathieu desnoyers" <mathieu.desnoyers at efficios.com>
> Sent: Monday, March 17, 2014 5:22:01 AM
> Subject: [PATCH lttng-ust] Fix: Make deadlocks with baddr statedump unlikely

Hi Paul,

A partial fix changing the code and leaving the bug in place is not
interesting for us, and will add a maintainance burden (extra delta
between current master and stable-2.4) for an experimental feature.

You might want to focus on getting the right fix in for 2.5, while we
are still in the development cycle.

Thanks,

Mathieu

> 
> Signed-off-by: Paul Woegerer <paul_woegerer at mentor.com>
> ---
>  liblttng-ust/lttng-ust-baddr.c | 95
>  ++++++++++++++++++++++++++++++++----------
>  1 file changed, 74 insertions(+), 21 deletions(-)
> 
> diff --git a/liblttng-ust/lttng-ust-baddr.c b/liblttng-ust/lttng-ust-baddr.c
> index dec7e82..0e8ff24 100644
> --- a/liblttng-ust/lttng-ust-baddr.c
> +++ b/liblttng-ust/lttng-ust-baddr.c
> @@ -39,17 +39,50 @@
>  #define TP_SESSION_CHECK
>  #include "ust_baddr_statedump.h"
>  
> +struct baddr_entry {
> +	void *base_addr_ptr;
> +	char resolved_path[PATH_MAX];
> +	int vdso;
> +};
> +
>  struct extract_data {
> -	void *owner;
>  	void *exec_baddr;	/* executable base address */
> +	struct baddr_entry *baddrs;	/* other base addresses */
> +	size_t num_baddrs;		/* number of other base addresses */
> +	size_t idx_baddrs;		/* current base addresse index */
>  };
>  
> +static
> +int add_baddr(void *base_addr_ptr,
> +	const char *resolved_path,
> +	int vdso,
> +	struct extract_data *data)
> +{
> +	struct baddr_entry *baddr;
> +
> +	if (data->num_baddrs < data->idx_baddrs + 1) {
> +		data->num_baddrs *= 2;
> +		data->baddrs = realloc(data->baddrs,
> +			data->num_baddrs * sizeof(struct baddr_entry));
> +		if (!data->baddrs)
> +			return 1;
> +	}
> +
> +	baddr = data->baddrs + data->idx_baddrs;
> +	baddr->base_addr_ptr = base_addr_ptr;
> +	strncpy(baddr->resolved_path, resolved_path, PATH_MAX - 1);
> +	baddr->vdso = vdso;
> +
> +	data->idx_baddrs += 1;
> +	return 0;
> +}
> +
>  /*
>   * Trace baddr into all sessions for which statedump is pending owned by
>   * the caller thread.
>   */
>  static
> -int trace_baddr(void *base_addr_ptr,
> +void trace_baddr(void *base_addr_ptr,
>  	const char *resolved_path,
>  	int vdso,
>  	void *owner)
> @@ -62,16 +95,6 @@ int trace_baddr(void *base_addr_ptr,
>  		sostat.st_size = 0;
>  		sostat.st_mtime = -1;
>  	}
> -	/*
> -	 * UST lock nests within dynamic loader lock.
> -	 */
> -	if (ust_lock()) {
> -		/*
> -		 * Stop iteration on headers if need to exit.
> -		 */
> -		ust_unlock();
> -		return 1;
> -	}
>  
>  	sessionsp = _lttng_get_sessions();
>  	cds_list_for_each_entry(session, sessionsp, node) {
> @@ -84,8 +107,6 @@ int trace_baddr(void *base_addr_ptr,
>  				resolved_path, sostat.st_size,
>  				sostat.st_mtime);
>  	}
> -	ust_unlock();
> -	return 0;
>  }
>  
>  static
> @@ -93,7 +114,6 @@ int extract_soinfo_events(struct dl_phdr_info *info,
> size_t size, void *_data)
>  {
>  	int j;
>  	struct extract_data *data = _data;
> -	void *owner = data->owner;
>  
>  	for (j = 0; j < info->dlpi_phnum; j++) {
>  		char resolved_path[PATH_MAX];
> @@ -138,9 +158,8 @@ int extract_soinfo_events(struct dl_phdr_info *info,
> size_t size, void *_data)
>  				vdso = 1;
>  			}
>  		}
> -		if (trace_baddr(base_addr_ptr, resolved_path, vdso, owner)) {
> +		if (add_baddr(base_addr_ptr, resolved_path, vdso, data))
>  			return 1;
> -		}
>  		/*
>  		 * We are only interested in the base address (lowest virtual
>  		 * address associated with the memory image), skip the rest
> @@ -151,9 +170,8 @@ int extract_soinfo_events(struct dl_phdr_info *info,
> size_t size, void *_data)
>  }
>  
>  static
> -void dump_exec_baddr(struct extract_data *data)
> +void dump_exec_baddr(struct extract_data *data, void *owner)
>  {
> -	void *owner = data->owner;
>  	void *base_addr_ptr;
>  	char exe_path[PATH_MAX];
>  	ssize_t exe_len;
> @@ -172,6 +190,38 @@ void dump_exec_baddr(struct extract_data *data)
>  	trace_baddr(base_addr_ptr, exe_path, 0, owner);
>  }
>  
> +static
> +void dump_baddrs(struct extract_data *data, void *owner)
> +{
> +	/* Emit tracepoints for shared objects */
> +	struct baddr_entry *baddrs = data->baddrs;
> +	size_t idx_baddrs = data->idx_baddrs;
> +	size_t i = 0;
> +
> +	/*
> +	 * UST lock nests within dynamic loader lock.
> +	 */
> +	if (ust_lock()) {
> +		/*
> +		 * Stop if need to exit.
> +		 */
> +		ust_unlock();
> +		return;
> +	}
> +
> +	while (i < idx_baddrs) {
> +		struct baddr_entry *baddr = baddrs + i;
> +		trace_baddr(baddr->base_addr_ptr,
> +			baddr->resolved_path,
> +			baddr->vdso, owner);
> +		i += 1;
> +	}
> +	/* Emit tracepoint for executable */
> +	dump_exec_baddr(data, owner);
> +
> +	ust_unlock();
> +}
> +
>  int lttng_ust_baddr_statedump(void *owner)
>  {
>  	struct extract_data data;
> @@ -179,8 +229,10 @@ int lttng_ust_baddr_statedump(void *owner)
>  	if (!getenv("LTTNG_UST_WITH_EXPERIMENTAL_BADDR_STATEDUMP"))
>  		return 0;
>  
> -	data.owner = owner;
>  	data.exec_baddr = NULL;
> +	data.num_baddrs = 32;
> +	data.baddrs = malloc(data.num_baddrs * sizeof(struct baddr_entry));
> +	data.idx_baddrs = 0;
>  	/*
>  	 * Iterate through the list of currently loaded shared objects and
>  	 * generate events for loadable segments using
> @@ -193,7 +245,8 @@ int lttng_ust_baddr_statedump(void *owner)
>  	 * deadlocks, so dump the executable outside of the phdr
>  	 * iteration.
>  	 */
> -	dump_exec_baddr(&data);
> +	dump_baddrs(&data, owner);
> +	free(data.baddrs);
>  	return 0;
>  }
>  
> --
> 1.9.0
> 
> 

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com



More information about the lttng-dev mailing list