mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-16 00:15:01 +00:00
check pthread_atfork and thread-local storage
Add pthread_atfork check to configure.ac and uses it when necessary,
Introduces tls.m4 macro for checking thread-local storage support, Puts
values array into thread-local storage
(lxc_global_config_value@src/lxc/utils.c), Removes
static_lock/static_unlock from LXC code.
Lastly, it introduces a warning for bionic users about multithreaded
usage of LXC.
(requires 64b1be2903
to be reverted first)
Signed-off-by: S.Çağlar Onur <caglar@10ur.org>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
parent
67c4fe9b2d
commit
babbea4b30
14
config/tls.m4
Normal file
14
config/tls.m4
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# See if we have working TLS. We only check to see if it compiles, and that
|
||||||
|
# the resulting program actually runs, not whether the resulting TLS variables
|
||||||
|
# work properly; that check is done at runtime, since we can run binaries
|
||||||
|
# compiled with __thread on systems without TLS.
|
||||||
|
AC_DEFUN([LXC_CHECK_TLS],
|
||||||
|
[
|
||||||
|
AC_MSG_CHECKING(for TLS)
|
||||||
|
AC_RUN_IFELSE([AC_LANG_SOURCE([[ static __thread int val; int main() { return 0; } ]])],[have_tls=yes],[have_tls=no],[have_tls=no ])
|
||||||
|
AC_MSG_RESULT($have_tls)
|
||||||
|
if test "$have_tls" = "yes"; then
|
||||||
|
AC_DEFINE([HAVE_TLS],[1],[Define if the compiler supports __thread])
|
||||||
|
AC_DEFINE([thread_local],[__thread],[Define to the compiler TLS keyword])
|
||||||
|
fi
|
||||||
|
])
|
15
configure.ac
15
configure.ac
@ -483,6 +483,8 @@ AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/capability.h sys/personalit
|
|||||||
AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr])
|
AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr])
|
||||||
|
|
||||||
# Check for some functions
|
# Check for some functions
|
||||||
|
AC_CHECK_LIB(pthread, main)
|
||||||
|
AC_CHECK_FUNCS(pthread_atfork)
|
||||||
AC_CHECK_LIB(util, openpty)
|
AC_CHECK_LIB(util, openpty)
|
||||||
AC_CHECK_FUNCS([openpty hasmntopt setmntent endmntent])
|
AC_CHECK_FUNCS([openpty hasmntopt setmntent endmntent])
|
||||||
AC_CHECK_FUNCS([getline],
|
AC_CHECK_FUNCS([getline],
|
||||||
@ -502,6 +504,9 @@ AC_SEARCH_LIBS(clock_gettime, [rt])
|
|||||||
AC_PROG_GCC_TRADITIONAL
|
AC_PROG_GCC_TRADITIONAL
|
||||||
AC_PROG_SED
|
AC_PROG_SED
|
||||||
|
|
||||||
|
# See if we support thread-local storage.
|
||||||
|
LXC_CHECK_TLS
|
||||||
|
|
||||||
if test "x$GCC" = "xyes"; then
|
if test "x$GCC" = "xyes"; then
|
||||||
CFLAGS="$CFLAGS -Wall -Werror"
|
CFLAGS="$CFLAGS -Wall -Werror"
|
||||||
fi
|
fi
|
||||||
@ -680,3 +685,13 @@ Debugging:
|
|||||||
Paths:
|
Paths:
|
||||||
- Logs in configpath: $enable_configpath_log
|
- Logs in configpath: $enable_configpath_log
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if test "x$ac_cv_func_pthread_atfork" = "xno" ; then
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
WARNING: Threading not supported on your platform
|
||||||
|
|
||||||
|
You are compiling LXC for bionic target which lacks certain threading related functionality used by LXC API (like pthread_atfork).
|
||||||
|
Please note that, because of the missing functionality, multithreaded usage of LXC API cause some problems.
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
@ -46,7 +46,6 @@ lxc_log_define(lxc_lock, lxc);
|
|||||||
|
|
||||||
#ifdef MUTEX_DEBUGGING
|
#ifdef MUTEX_DEBUGGING
|
||||||
static pthread_mutex_t thread_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
static pthread_mutex_t thread_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
||||||
static pthread_mutex_t static_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
|
||||||
|
|
||||||
static inline void dump_stacktrace(void)
|
static inline void dump_stacktrace(void)
|
||||||
{
|
{
|
||||||
@ -68,7 +67,6 @@ static inline void dump_stacktrace(void)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
static inline void dump_stacktrace(void) {;}
|
static inline void dump_stacktrace(void) {;}
|
||||||
#endif
|
#endif
|
||||||
@ -326,28 +324,13 @@ void process_unlock(void)
|
|||||||
* to unlock the mutex.
|
* to unlock the mutex.
|
||||||
* This forbids doing fork() while explicitly holding the lock.
|
* This forbids doing fork() while explicitly holding the lock.
|
||||||
*/
|
*/
|
||||||
|
#ifdef HAVE_PTHREAD_ATFORK
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void process_lock_setup_atfork(void)
|
static void process_lock_setup_atfork(void)
|
||||||
{
|
{
|
||||||
pthread_atfork(process_lock, process_unlock, process_unlock);
|
pthread_atfork(process_lock, process_unlock, process_unlock);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Protects static const values inside the lxc_global_config_value funtion */
|
|
||||||
void static_lock(void)
|
|
||||||
{
|
|
||||||
lock_mutex(&static_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void static_unlock(void)
|
|
||||||
{
|
|
||||||
unlock_mutex(&static_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((constructor))
|
|
||||||
static void static_lock_setup_atfork(void)
|
|
||||||
{
|
|
||||||
pthread_atfork(static_lock, static_unlock, static_unlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int container_mem_lock(struct lxc_container *c)
|
int container_mem_lock(struct lxc_container *c)
|
||||||
{
|
{
|
||||||
|
@ -123,16 +123,6 @@ extern void process_lock(void);
|
|||||||
*/
|
*/
|
||||||
extern void process_unlock(void);
|
extern void process_unlock(void);
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Lock global data.
|
|
||||||
*/
|
|
||||||
extern void static_lock(void);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Unlock global data.
|
|
||||||
*/
|
|
||||||
extern void static_unlock(void);
|
|
||||||
|
|
||||||
struct lxc_container;
|
struct lxc_container;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -250,9 +250,12 @@ static const char *lxc_global_config_value(const char *option_name)
|
|||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Protected by a mutex to eliminate conflicting load and store operations */
|
/* placed in the thread local storage pool for non-bionic targets */
|
||||||
|
#ifdef HAVE_TLS
|
||||||
|
static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
|
||||||
|
#else
|
||||||
static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
|
static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
|
||||||
|
#endif
|
||||||
char *user_config_path = NULL;
|
char *user_config_path = NULL;
|
||||||
char *user_lxc_path = NULL;
|
char *user_lxc_path = NULL;
|
||||||
|
|
||||||
@ -273,7 +276,6 @@ static const char *lxc_global_config_value(const char *option_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char * const (*ptr)[2];
|
const char * const (*ptr)[2];
|
||||||
const char *value;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
char buf[1024], *p, *p2;
|
char buf[1024], *p, *p2;
|
||||||
FILE *fin = NULL;
|
FILE *fin = NULL;
|
||||||
@ -289,15 +291,11 @@ static const char *lxc_global_config_value(const char *option_name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static_lock();
|
|
||||||
if (values[i]) {
|
if (values[i]) {
|
||||||
free(user_config_path);
|
free(user_config_path);
|
||||||
free(user_lxc_path);
|
free(user_lxc_path);
|
||||||
value = values[i];
|
return values[i];
|
||||||
static_unlock();
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
static_unlock();
|
|
||||||
|
|
||||||
fin = fopen_cloexec(user_config_path, "r");
|
fin = fopen_cloexec(user_config_path, "r");
|
||||||
free(user_config_path);
|
free(user_config_path);
|
||||||
@ -333,15 +331,12 @@ static const char *lxc_global_config_value(const char *option_name)
|
|||||||
while (*p && (*p == ' ' || *p == '\t')) p++;
|
while (*p && (*p == ' ' || *p == '\t')) p++;
|
||||||
if (!*p)
|
if (!*p)
|
||||||
continue;
|
continue;
|
||||||
static_lock();
|
|
||||||
values[i] = copy_global_config_value(p);
|
values[i] = copy_global_config_value(p);
|
||||||
static_unlock();
|
|
||||||
free(user_lxc_path);
|
free(user_lxc_path);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* could not find value, use default */
|
/* could not find value, use default */
|
||||||
static_lock();
|
|
||||||
if (strcmp(option_name, "lxcpath") == 0)
|
if (strcmp(option_name, "lxcpath") == 0)
|
||||||
values[i] = user_lxc_path;
|
values[i] = user_lxc_path;
|
||||||
else {
|
else {
|
||||||
@ -353,16 +348,12 @@ static const char *lxc_global_config_value(const char *option_name)
|
|||||||
* as an error... */
|
* as an error... */
|
||||||
if (!values[i])
|
if (!values[i])
|
||||||
errno = 0;
|
errno = 0;
|
||||||
static_unlock();
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (fin)
|
if (fin)
|
||||||
fclose(fin);
|
fclose(fin);
|
||||||
|
|
||||||
static_lock();
|
return values[i];
|
||||||
value = values[i];
|
|
||||||
static_unlock();
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *default_lvm_vg(void)
|
const char *default_lvm_vg(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user