Merged revisions 76644 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r76644 | benjamin.peterson | 2009-12-02 20:52:39 -0600 (Wed, 02 Dec 2009) | 4 lines

  disable pymalloc tricks with the --with-valgrind option #2422

  Patch from James Henstridge.
........
This commit is contained in:
Benjamin Peterson 2009-12-03 03:01:27 +00:00
parent cb134d7d88
commit 05159c4a7b
5 changed files with 225 additions and 4 deletions

View File

@ -143,6 +143,11 @@ C-API
``const char *`` as the string is stored beyond the call. ``const char *`` as the string is stored beyond the call.
- Issue #2422: When compiled with the ``--with-valgrind`` option, the
pymalloc allocator will be automatically disabled when running under
Valgrind. This gives improved memory leak detection when running
under Valgrind, while taking advantage of pymalloc at other times.
Library Library
------- -------

View File

@ -2,6 +2,21 @@
#ifdef WITH_PYMALLOC #ifdef WITH_PYMALLOC
#ifdef WITH_VALGRIND
#include <valgrind/valgrind.h>
/* If we're using GCC, use __builtin_expect() to reduce overhead of
the valgrind checks */
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
# define UNLIKELY(value) __builtin_expect((value), 0)
#else
# define UNLIKELY(value) (value)
#endif
/* -1 indicates that we haven't checked that we're running on valgrind yet. */
static int running_on_valgrind = -1;
#endif
/* An object allocator for Python. /* An object allocator for Python.
Here is an introduction to the layers of the Python memory architecture, Here is an introduction to the layers of the Python memory architecture,
@ -728,6 +743,13 @@ PyObject_Malloc(size_t nbytes)
poolp next; poolp next;
uint size; uint size;
#ifdef WITH_VALGRIND
if (UNLIKELY(running_on_valgrind == -1))
running_on_valgrind = RUNNING_ON_VALGRIND;
if (UNLIKELY(running_on_valgrind))
goto redirect;
#endif
/* /*
* Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes. * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.
* Most python internals blindly use a signed Py_ssize_t to track * Most python internals blindly use a signed Py_ssize_t to track
@ -927,6 +949,11 @@ PyObject_Free(void *p)
if (p == NULL) /* free(NULL) has no effect */ if (p == NULL) /* free(NULL) has no effect */
return; return;
#ifdef WITH_VALGRIND
if (UNLIKELY(running_on_valgrind > 0))
goto redirect;
#endif
pool = POOL_ADDR(p); pool = POOL_ADDR(p);
if (Py_ADDRESS_IN_RANGE(p, pool)) { if (Py_ADDRESS_IN_RANGE(p, pool)) {
/* We allocated this address. */ /* We allocated this address. */
@ -1121,6 +1148,9 @@ PyObject_Free(void *p)
return; return;
} }
#ifdef WITH_VALGRIND
redirect:
#endif
/* We didn't allocate this address. */ /* We didn't allocate this address. */
free(p); free(p);
} }
@ -1150,6 +1180,12 @@ PyObject_Realloc(void *p, size_t nbytes)
if (nbytes > PY_SSIZE_T_MAX) if (nbytes > PY_SSIZE_T_MAX)
return NULL; return NULL;
#ifdef WITH_VALGRIND
/* Treat running_on_valgrind == -1 the same as 0 */
if (UNLIKELY(running_on_valgrind > 0))
goto redirect;
#endif
pool = POOL_ADDR(p); pool = POOL_ADDR(p);
if (Py_ADDRESS_IN_RANGE(p, pool)) { if (Py_ADDRESS_IN_RANGE(p, pool)) {
/* We're in charge of this block */ /* We're in charge of this block */
@ -1177,6 +1213,9 @@ PyObject_Realloc(void *p, size_t nbytes)
} }
return bp; return bp;
} }
#ifdef WITH_VALGRIND
redirect:
#endif
/* We're not managing this block. If nbytes <= /* We're not managing this block. If nbytes <=
* SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this
* block. However, if we do, we need to copy the valid data from * block. However, if we do, we need to copy the valid data from

163
configure vendored
View File

@ -1,5 +1,5 @@
#! /bin/sh #! /bin/sh
# From configure.in Revision: 76566 . # From configure.in Revision: 76637 .
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for python 3.2. # Generated by GNU Autoconf 2.61 for python 3.2.
# #
@ -1355,6 +1355,7 @@ Optional Packages:
--with(out)-doc-strings disable/enable documentation strings --with(out)-doc-strings disable/enable documentation strings
--with(out)-tsc enable/disable timestamp counter profile --with(out)-tsc enable/disable timestamp counter profile
--with(out)-pymalloc disable/enable specialized mallocs --with(out)-pymalloc disable/enable specialized mallocs
--with-valgrind Enable Valgrind support
--with-wctype-functions use wctype.h functions --with-wctype-functions use wctype.h functions
--with-fpectl enable SIGFPE catching --with-fpectl enable SIGFPE catching
--with-libm=STRING math library --with-libm=STRING math library
@ -17107,6 +17108,166 @@ fi
{ echo "$as_me:$LINENO: result: $with_pymalloc" >&5 { echo "$as_me:$LINENO: result: $with_pymalloc" >&5
echo "${ECHO_T}$with_pymalloc" >&6; } echo "${ECHO_T}$with_pymalloc" >&6; }
# Check for Valgrind support
{ echo "$as_me:$LINENO: checking for --with-valgrind" >&5
echo $ECHO_N "checking for --with-valgrind... $ECHO_C" >&6; }
# Check whether --with-valgrind was given.
if test "${with_valgrind+set}" = set; then
withval=$with_valgrind;
else
with_valgrind=no
fi
{ echo "$as_me:$LINENO: result: $with_valgrind" >&5
echo "${ECHO_T}$with_valgrind" >&6; }
if test "$with_valgrind" != no; then
if test "${ac_cv_header_valgrind_valgrind_h+set}" = set; then
{ echo "$as_me:$LINENO: checking for valgrind/valgrind.h" >&5
echo $ECHO_N "checking for valgrind/valgrind.h... $ECHO_C" >&6; }
if test "${ac_cv_header_valgrind_valgrind_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
{ echo "$as_me:$LINENO: result: $ac_cv_header_valgrind_valgrind_h" >&5
echo "${ECHO_T}$ac_cv_header_valgrind_valgrind_h" >&6; }
else
# Is the header compilable?
{ echo "$as_me:$LINENO: checking valgrind/valgrind.h usability" >&5
echo $ECHO_N "checking valgrind/valgrind.h usability... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <valgrind/valgrind.h>
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6; }
# Is the header present?
{ echo "$as_me:$LINENO: checking valgrind/valgrind.h presence" >&5
echo $ECHO_N "checking valgrind/valgrind.h presence... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <valgrind/valgrind.h>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: valgrind/valgrind.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: valgrind/valgrind.h: in the future, the compiler will take precedence" >&2;}
( cat <<\_ASBOX
## -------------------------------------- ##
## Report this to http://bugs.python.org/ ##
## -------------------------------------- ##
_ASBOX
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ echo "$as_me:$LINENO: checking for valgrind/valgrind.h" >&5
echo $ECHO_N "checking for valgrind/valgrind.h... $ECHO_C" >&6; }
if test "${ac_cv_header_valgrind_valgrind_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_cv_header_valgrind_valgrind_h=$ac_header_preproc
fi
{ echo "$as_me:$LINENO: result: $ac_cv_header_valgrind_valgrind_h" >&5
echo "${ECHO_T}$ac_cv_header_valgrind_valgrind_h" >&6; }
fi
if test $ac_cv_header_valgrind_valgrind_h = yes; then
cat >>confdefs.h <<\_ACEOF
#define WITH_VALGRIND 1
_ACEOF
else
{ { echo "$as_me:$LINENO: error: Valgrind support requested but headers not available" >&5
echo "$as_me: error: Valgrind support requested but headers not available" >&2;}
{ (exit 1); exit 1; }; }
fi
fi
# Check for --with-wctype-functions # Check for --with-wctype-functions
{ echo "$as_me:$LINENO: checking for --with-wctype-functions" >&5 { echo "$as_me:$LINENO: checking for --with-wctype-functions" >&5
echo $ECHO_N "checking for --with-wctype-functions... $ECHO_C" >&6; } echo $ECHO_N "checking for --with-wctype-functions... $ECHO_C" >&6; }

View File

@ -2345,6 +2345,19 @@ then
fi fi
AC_MSG_RESULT($with_pymalloc) AC_MSG_RESULT($with_pymalloc)
# Check for Valgrind support
AC_MSG_CHECKING([for --with-valgrind])
AC_ARG_WITH([valgrind],
AC_HELP_STRING([--with-valgrind], [Enable Valgrind support]),,
with_valgrind=no)
AC_MSG_RESULT([$with_valgrind])
if test "$with_valgrind" != no; then
AC_CHECK_HEADER([valgrind/valgrind.h],
[AC_DEFINE([WITH_VALGRIND], 1, [Define if you want pymalloc to be disabled when running under valgrind])],
[AC_MSG_ERROR([Valgrind support requested but headers not available])]
)
fi
# Check for --with-wctype-functions # Check for --with-wctype-functions
AC_MSG_CHECKING(for --with-wctype-functions) AC_MSG_CHECKING(for --with-wctype-functions)
AC_ARG_WITH(wctype-functions, AC_ARG_WITH(wctype-functions,

View File

@ -299,9 +299,6 @@
/* Define to 1 if you have the `getpeername' function. */ /* Define to 1 if you have the `getpeername' function. */
#undef HAVE_GETPEERNAME #undef HAVE_GETPEERNAME
/* Define to 1 if you have the `initgroups' function. */
#undef HAVE_INITGROUPS
/* Define to 1 if you have the `getpgid' function. */ /* Define to 1 if you have the `getpgid' function. */
#undef HAVE_GETPGID #undef HAVE_GETPGID
@ -356,6 +353,9 @@
/* Define if you have the 'inet_pton' function. */ /* Define if you have the 'inet_pton' function. */
#undef HAVE_INET_PTON #undef HAVE_INET_PTON
/* Define to 1 if you have the `initgroups' function. */
#undef HAVE_INITGROUPS
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
@ -1065,6 +1065,9 @@
/* Define to profile with the Pentium timestamp counter */ /* Define to profile with the Pentium timestamp counter */
#undef WITH_TSC #undef WITH_TSC
/* Define if you want pymalloc to be disabled when running under valgrind */
#undef WITH_VALGRIND
/* Define to 1 if your processor stores words with the most significant byte /* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */ first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN #undef WORDS_BIGENDIAN