From 38589c46c02c254489eedf73680fb2334ca4fa33 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Tue, 14 Apr 2015 15:34:21 -0600 Subject: [PATCH 1/2] opal: add a destructor/fini function to opal This commit is related to an RFC from June 2014. Disscussion can be found at: http://www.open-mpi.org/community/lists/devel/2014/07/15140.php The finalize function is set using either the linker option -fini or __attribute__((destructor)) depending on compiler support. I have confirmed that this hybrid approach works with all the major compilers. The attribute is supported by gcc, clang, llvm, xlc, and icc. The fini function will support pgi. If a compiler/linker combination does not support either the destructor or fini function a message will be printed on re-init indicating it is not supported (an improvement over the current behavior-- SEGV). I moved the following to the destructor function: - Class system finalize. This solves a bug when MPI_T_finalize is called before MPI_Init. The only downside to this change is we will leave the footprint of the opal class system after MPI_Finalize. This footprint should be relatively small. This is an alternative to #517 but the two PRs are not mutually-exclusive (with some modifications). This commit should also be safe for 1.8.x as it does not change internal or external ABI (#517 changes internal ABI). Signed-off-by: Nathan Hjelm --- config/opal_check_attributes.m4 | 1 + configure.ac | 14 ++++++++++++++ opal/Makefile.am | 11 +++++++++++ opal/runtime/opal_finalize.c | 17 +++++++++++++++-- opal/runtime/opal_init.c | 13 +++++++++++++ 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/config/opal_check_attributes.m4 b/config/opal_check_attributes.m4 index 88788f2677..a766a09ac6 100644 --- a/config/opal_check_attributes.m4 +++ b/config/opal_check_attributes.m4 @@ -608,4 +608,5 @@ AC_DEFUN([OPAL_CHECK_ATTRIBUTES], [ [Whether your compiler has __attribute__ weak alias or not]) AC_DEFINE_UNQUOTED(OPAL_HAVE_ATTRIBUTE_DESTRUCTOR, [$opal_cv___attribute__destructor], [Whether your compiler has __attribute__ destructor or not]) + AM_CONDITIONAL(HAVE_ATTRIBUTE_DESTRUCTOR, [test x$opal_cv___attribute__destructor = x1]) ]) diff --git a/configure.ac b/configure.ac index d103ab170a..b2ed70eb61 100644 --- a/configure.ac +++ b/configure.ac @@ -799,6 +799,20 @@ m4_ifdef([project_ompi], [OMPI_FIND_MPI_AINT_COUNT_OFFSET]) # checkpoint results AC_CACHE_SAVE +################################## +# Linker characteristics +################################## + +AC_MSG_CHECKING([the linker for support for the -fini option]) +LDFLAGS_save=$LDFLAGS +LDFLAGS="$LDFLAGS_save -Wl,-fini -Wl,finalize" +AC_TRY_LINK([void finalize (void) {}], [], [AC_MSG_RESULT([yes]) + opal_ld_fini=1], [AC_MSG_RESULT([no]) + opal_ld_fini=0]) +AM_CONDITIONAL(HAVE_LD_FINI, [test x$opal_ld_fini = x1]) +AC_DEFINE_UNQUOTED(OPAL_HAVE_LD_FINI, [$opal_ld_fini], + [Whether linker has support for the -fini option]) +LDFLAGS=$LDFLAGS_save ################################## # Libraries diff --git a/opal/Makefile.am b/opal/Makefile.am index 360474ab0e..630b18274f 100644 --- a/opal/Makefile.am +++ b/opal/Makefile.am @@ -53,8 +53,19 @@ lib@OPAL_LIB_PREFIX@open_pal_la_LIBADD = \ util/libopalutil.la \ $(MCA_opal_FRAMEWORK_LIBS) lib@OPAL_LIB_PREFIX@open_pal_la_DEPENDENCIES = $(lib@OPAL_LIB_PREFIX@open_pal_la_LIBADD) + +if HAVE_ATTRIBUTE_DESTRUCTOR + lib@OPAL_LIB_PREFIX@open_pal_la_LDFLAGS = -version-info $(libopen_pal_so_version) +else +if HAVE_LD_FINI + +lib@OPAL_LIB_PREFIX@open_pal_la_LDFLAGS = -version-info $(libopen_pal_so_version) -Wl,-fini,opal_cleanup + +endif +endif + # included subdirectory Makefile.am's and appended-to variables headers = noinst_LTLIBRARIES = diff --git a/opal/runtime/opal_finalize.c b/opal/runtime/opal_finalize.c index 5a123989e8..a897c5ee3f 100644 --- a/opal/runtime/opal_finalize.c +++ b/opal/runtime/opal_finalize.c @@ -57,6 +57,18 @@ extern int opal_initialized; extern int opal_util_initialized; +extern bool opal_init_called; + +static void __opal_attribute_destructor__ opal_cleanup (void) +{ + if (!opal_initialized) { + /* nothing to do */ + return; + } + + /* finalize the class/object system */ + opal_class_finalize(); +} int opal_finalize_util(void) @@ -101,8 +113,9 @@ opal_finalize_util(void) opal_datatype_finalize(); - /* finalize the class/object system */ - opal_class_finalize(); +#if !(OPAL_HAVE_LD_FINI || OPAL_HAVE_ATTRIBUTE_DESTRUCTOR) + opal_cleanup (); +#endif free (opal_process_info.nodename); opal_process_info.nodename = NULL; diff --git a/opal/runtime/opal_init.c b/opal/runtime/opal_init.c index 7ae32a4b41..837922602e 100644 --- a/opal/runtime/opal_init.c +++ b/opal/runtime/opal_init.c @@ -74,6 +74,7 @@ const char opal_version_string[] = OPAL_IDENT_STRING; int opal_initialized = 0; +bool opal_init_called = false; int opal_util_initialized = 0; /* We have to put a guess in here in case hwloc is not available. If hwloc is available, this value will be overwritten when the @@ -266,6 +267,18 @@ opal_init_util(int* pargc, char*** pargv) return OPAL_SUCCESS; } +#if !(OPAL_HAVE_LD_FINI || OPAL_HAVE_ATTRIBUTE_DESTRUCTOR) + if (opal_init_called) { + /* can't use show_help here */ + fprintf (stderr, "opal_init_util: attempted to initialize after finalize without compiler " + "support for either __attribute__(destructor) or linker support for -fini -- process " + "will likely abort\n"); + return OPAL_ERR_NOT_SUPPORTED; + } +#endif + + opal_init_called = true; + /* set the nodename right away so anyone who needs it has it. Note * that we don't bother with fqdn and prefix issues here - we let * the RTE later replace this with a modified name if the user From 662460b06b8a93f1d3725aa13246190960dd0602 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Mon, 20 Apr 2015 09:51:06 -0600 Subject: [PATCH 2/2] Modify destructor function configury Signed-off-by: Nathan Hjelm --- config/opal_check_attributes.m4 | 1 - configure.ac | 21 ++++++++++++++++----- opal/Makefile.am | 9 ++------- opal/runtime/opal_finalize.c | 2 +- opal/runtime/opal_init.c | 2 +- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/config/opal_check_attributes.m4 b/config/opal_check_attributes.m4 index a766a09ac6..88788f2677 100644 --- a/config/opal_check_attributes.m4 +++ b/config/opal_check_attributes.m4 @@ -608,5 +608,4 @@ AC_DEFUN([OPAL_CHECK_ATTRIBUTES], [ [Whether your compiler has __attribute__ weak alias or not]) AC_DEFINE_UNQUOTED(OPAL_HAVE_ATTRIBUTE_DESTRUCTOR, [$opal_cv___attribute__destructor], [Whether your compiler has __attribute__ destructor or not]) - AM_CONDITIONAL(HAVE_ATTRIBUTE_DESTRUCTOR, [test x$opal_cv___attribute__destructor = x1]) ]) diff --git a/configure.ac b/configure.ac index b2ed70eb61..1d5bc2909b 100644 --- a/configure.ac +++ b/configure.ac @@ -807,13 +807,24 @@ AC_MSG_CHECKING([the linker for support for the -fini option]) LDFLAGS_save=$LDFLAGS LDFLAGS="$LDFLAGS_save -Wl,-fini -Wl,finalize" AC_TRY_LINK([void finalize (void) {}], [], [AC_MSG_RESULT([yes]) - opal_ld_fini=1], [AC_MSG_RESULT([no]) - opal_ld_fini=0]) -AM_CONDITIONAL(HAVE_LD_FINI, [test x$opal_ld_fini = x1]) -AC_DEFINE_UNQUOTED(OPAL_HAVE_LD_FINI, [$opal_ld_fini], - [Whether linker has support for the -fini option]) + opal_ld_have_fini=1], [AC_MSG_RESULT([no]) + opal_ld_have_fini=0]) LDFLAGS=$LDFLAGS_save +opal_destructor_use_fini=0 +opal_no_destructor=0 +if test x$opal_cv___attribute__destructor = x0 ; then + if test x$opal_ld_have_fini = x1 ; then + opal_destructor_use_fini=1 + else + opal_no_destructor=1; + fi +fi + +AC_DEFINE_UNQUOTED(OPAL_NO_LIB_DESTRUCTOR, [$opal_no_destructor], + [Whether libraries can be configured with destructor functions]) +AM_CONDITIONAL(OPAL_DESTRUCTOR_USE_FINI, [test x$opal_destructor_use_fini = x1]) + ################################## # Libraries ################################## diff --git a/opal/Makefile.am b/opal/Makefile.am index 630b18274f..dddfe4b6cb 100644 --- a/opal/Makefile.am +++ b/opal/Makefile.am @@ -53,17 +53,12 @@ lib@OPAL_LIB_PREFIX@open_pal_la_LIBADD = \ util/libopalutil.la \ $(MCA_opal_FRAMEWORK_LIBS) lib@OPAL_LIB_PREFIX@open_pal_la_DEPENDENCIES = $(lib@OPAL_LIB_PREFIX@open_pal_la_LIBADD) - -if HAVE_ATTRIBUTE_DESTRUCTOR - lib@OPAL_LIB_PREFIX@open_pal_la_LDFLAGS = -version-info $(libopen_pal_so_version) -else -if HAVE_LD_FINI +if OPAL_DESTRUCTOR_USE_FINI -lib@OPAL_LIB_PREFIX@open_pal_la_LDFLAGS = -version-info $(libopen_pal_so_version) -Wl,-fini,opal_cleanup +lib@OPAL_LIB_PREFIX@open_pal_la_LDFLAGS += -Wl,-fini -Wl,opal_cleanup -endif endif # included subdirectory Makefile.am's and appended-to variables diff --git a/opal/runtime/opal_finalize.c b/opal/runtime/opal_finalize.c index a897c5ee3f..ceebeb99e1 100644 --- a/opal/runtime/opal_finalize.c +++ b/opal/runtime/opal_finalize.c @@ -113,7 +113,7 @@ opal_finalize_util(void) opal_datatype_finalize(); -#if !(OPAL_HAVE_LD_FINI || OPAL_HAVE_ATTRIBUTE_DESTRUCTOR) +#if OPAL_NO_LIB_DESTRUCTOR opal_cleanup (); #endif diff --git a/opal/runtime/opal_init.c b/opal/runtime/opal_init.c index 837922602e..180827cf66 100644 --- a/opal/runtime/opal_init.c +++ b/opal/runtime/opal_init.c @@ -267,7 +267,7 @@ opal_init_util(int* pargc, char*** pargv) return OPAL_SUCCESS; } -#if !(OPAL_HAVE_LD_FINI || OPAL_HAVE_ATTRIBUTE_DESTRUCTOR) +#if OPAL_NO_LIB_DESTRUCTOR if (opal_init_called) { /* can't use show_help here */ fprintf (stderr, "opal_init_util: attempted to initialize after finalize without compiler "