[dm-devel] [PATCH 3/3] multipathd: add code to initalize unwinder

Benjamin Marzinski bmarzins at redhat.com
Tue Feb 2 04:10:39 UTC 2021


On Thu, Jan 28, 2021 at 09:45:44PM +0100, mwilck at suse.com wrote:
> From: Martin Wilck <mwilck at suse.com>
> 
> glibc's implementation of pthread_cancel() loads symbols from
> libgcc_s.so using dlopen() when pthread_cancel() is called
> for the first time. This happens even with LD_BIND_NOW=1.
> This may imply the need for file system access when a thread is
> cancelled, which in the case of multipath-tools might be in a
> dangerous situation where multipathd must avoid blocking.
> 
> Call load_unwinder() during startup to make sure the dynamic
> linker has all necessary symbols resolved early on.
> 
> This implementation simply creates a dummy thread and cancels
> it. This way all necessary symbols for thread cancellation
> will be loaded, no matter what the C library needs to implement
> cancellation.
> 
Reviewed-by: Benjamin Marzinski <bmarzins at redhat.com>
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
>  multipathd/Makefile        |  2 +-
>  multipathd/init_unwinder.c | 34 ++++++++++++++++++++++++++++++++++
>  multipathd/init_unwinder.h | 21 +++++++++++++++++++++
>  multipathd/main.c          |  2 ++
>  4 files changed, 58 insertions(+), 1 deletion(-)
>  create mode 100644 multipathd/init_unwinder.c
>  create mode 100644 multipathd/init_unwinder.h
> 
> diff --git a/multipathd/Makefile b/multipathd/Makefile
> index 632b82b..d053c1e 100644
> --- a/multipathd/Makefile
> +++ b/multipathd/Makefile
> @@ -30,7 +30,7 @@ ifeq ($(ENABLE_DMEVENTS_POLL),0)
>  endif
>  
>  OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o \
> -       dmevents.o
> +       dmevents.o init_unwinder.o
>  
>  EXEC = multipathd
>  
> diff --git a/multipathd/init_unwinder.c b/multipathd/init_unwinder.c
> new file mode 100644
> index 0000000..14467f3
> --- /dev/null
> +++ b/multipathd/init_unwinder.c
> @@ -0,0 +1,34 @@
> +#include <pthread.h>
> +#include <unistd.h>
> +#include "init_unwinder.h"
> +
> +static pthread_mutex_t dummy_mtx = PTHREAD_MUTEX_INITIALIZER;
> +static pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER;
> +
> +static void *dummy_thread(void *arg __attribute__((unused)))
> +{
> +	pthread_mutex_lock(&dummy_mtx);
> +	pthread_cond_broadcast(&dummy_cond);
> +	pthread_mutex_unlock(&dummy_mtx);
> +	pause();
> +	return NULL;
> +}
> +
> +int init_unwinder(void)
> +{
> +	pthread_t dummy;
> +	int rc;
> +
> +	pthread_mutex_lock(&dummy_mtx);
> +
> +	rc = pthread_create(&dummy, NULL, dummy_thread, NULL);
> +	if (rc != 0) {
> +		pthread_mutex_unlock(&dummy_mtx);
> +		return rc;
> +	}
> +
> +	pthread_cond_wait(&dummy_cond, &dummy_mtx);
> +	pthread_mutex_unlock(&dummy_mtx);
> +
> +	return pthread_cancel(dummy);
> +}
> diff --git a/multipathd/init_unwinder.h b/multipathd/init_unwinder.h
> new file mode 100644
> index 0000000..ada09f8
> --- /dev/null
> +++ b/multipathd/init_unwinder.h
> @@ -0,0 +1,21 @@
> +#ifndef _INIT_UNWINDER_H
> +#define _INIT_UNWINDER_H 1
> +
> +/*
> + * init_unwinder(): make sure unwinder symbols are loaded
> + *
> + * libc's implementation of pthread_cancel() loads symbols from
> + * libgcc_s.so using dlopen() when pthread_cancel() is called
> + * for the first time. This happens even with LD_BIND_NOW=1.
> + * This may imply the need for file system access when a thread is
> + * cancelled, which in the case of multipath-tools might be in a
> + * dangerous situation where multipathd must avoid blocking.
> + *
> + * Call load_unwinder() during startup to make sure the dynamic
> + * linker has all necessary symbols resolved early on.
> + *
> + * Return: 0 if successful, an error number otherwise.
> + */
> +int init_unwinder(void);
> +
> +#endif
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 99a89a6..6f851ae 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -83,6 +83,7 @@
>  #include "wwids.h"
>  #include "foreign.h"
>  #include "../third-party/valgrind/drd.h"
> +#include "init_unwinder.h"
>  
>  #define FILE_NAME_SIZE 256
>  #define CMDSIZE 160
> @@ -3041,6 +3042,7 @@ child (__attribute__((unused)) void *param)
>  	enum daemon_status state;
>  	int exit_code = 1;
>  
> +	init_unwinder();
>  	mlockall(MCL_CURRENT | MCL_FUTURE);
>  	signal_init();
>  	mp_rcu_data = setup_rcu();
> -- 
> 2.29.2




More information about the dm-devel mailing list