This patch adds the ability to use valgrind's memcheck tool to diagnose memory problems in git while running the test scripts. It works by placing a "fake" git in the front of the test script's PATH; this fake git runs the real git under valgrind. It also points the exec-path such that any stand-alone dashed git programs are run using the same script. In this way we avoid having to modify the actual git code in any way. To be certain that every call to any git executable is intercepted, the PATH is searched for executables beginning with "git-"; Scripts are excluded however. Valgrind can be used by specifying "GIT_TEST_OPTS=--valgrind" in the make invocation. Any invocation of git that finds any errors under valgrind will exit with failure code 126. Any valgrind output will go to the usual stderr channel for tests (i.e., /dev/null, unless -v has been specified). If you need to pass options to valgrind -- you might want to run another tool than memcheck, for example -- you can set the environment variable GIT_VALGRIND_OPTIONS. A few default suppressions are included, since libz seems to trigger quite a few false positives. We'll assume that libz works and that we can ignore any errors which are reported there. Initial patch and all the hard work by Jeff King. Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- AFAIR libz reserves only aligned memory, and does all operations in an aligned manner, but it is safe (even if it accesses uninitialized memory, it does not use the results anyway). t/test-lib.sh | 39 +++++++++++++++++++++++++++++++++++++-- t/valgrind/.gitignore | 2 ++ t/valgrind/default.supp | 21 +++++++++++++++++++++ t/valgrind/valgrind.sh | 12 ++++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 t/valgrind/.gitignore create mode 100644 t/valgrind/default.supp create mode 100755 t/valgrind/valgrind.sh diff --git a/t/test-lib.sh b/t/test-lib.sh index 41d5a59..1daae9b 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -94,6 +94,8 @@ do --no-python) # noop now... shift ;; + --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) + valgrind=t; shift ;; *) break ;; esac @@ -467,8 +469,41 @@ test_done () { # Test the binaries we have just built. The tests are kept in # t/ subdirectory and are run in 'trash directory' subdirectory. TEST_DIRECTORY=$(pwd) -PATH=$TEST_DIRECTORY/..:$PATH -GIT_EXEC_PATH=$(pwd)/.. +if test -z "$valgrind" +then + PATH=$TEST_DIRECTORY/..:$PATH + GIT_EXEC_PATH=$TEST_DIRECTORY/.. +else + # override all git executables in PATH and TEST_DIRECTORY/.. + GIT_VALGRIND=$TEST_DIRECTORY/valgrind + mkdir -p "$GIT_VALGRIND" + OLDIFS=$IFS + IFS=: + for path in $PATH:$TEST_DIRECTORY/.. + do + ls "$TEST_DIRECTORY"/../git "$path"/git-* 2> /dev/null | + while read file + do + # handle only executables + test -x "$file" || continue + + base=$(basename "$file") + test ! -h "$GIT_VALGRIND"/"$base" || continue + + if test "#!" = "$(head -c 2 < "$file")" + then + # do not override scripts + ln -s ../../"$base" "$GIT_VALGRIND"/"$base" + else + ln -s valgrind.sh "$GIT_VALGRIND"/"$base" + fi + done + done + IFS=$OLDIFS + PATH=$GIT_VALGRIND:$PATH + GIT_EXEC_PATH=$GIT_VALGRIND + export GIT_VALGRIND +fi GIT_TEMPLATE_DIR=$(pwd)/../templates/blt unset GIT_CONFIG GIT_CONFIG_NOSYSTEM=1 diff --git a/t/valgrind/.gitignore b/t/valgrind/.gitignore new file mode 100644 index 0000000..d781a63 --- /dev/null +++ b/t/valgrind/.gitignore @@ -0,0 +1,2 @@ +/git +/git-* diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp new file mode 100644 index 0000000..2482b3b --- /dev/null +++ b/t/valgrind/default.supp @@ -0,0 +1,21 @@ +{ + ignore-zlib-errors-cond + Memcheck:Cond + obj:*libz.so* +} + +{ + ignore-zlib-errors-value4 + Memcheck:Value4 + obj:*libz.so* +} + +{ + writing-data-from-zlib-triggers-errors + Memcheck:Param + write(buf) + obj:/lib/ld-*.so + fun:write_in_full + fun:write_buffer + fun:write_loose_object +} diff --git a/t/valgrind/valgrind.sh b/t/valgrind/valgrind.sh new file mode 100755 index 0000000..24f3a4e --- /dev/null +++ b/t/valgrind/valgrind.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +base=$(basename "$0") + +exec valgrind -q --error-exitcode=126 \ + --leak-check=no \ + --suppressions="$GIT_VALGRIND/default.supp" \ + --gen-suppressions=all \ + --log-fd=4 \ + --input-fd=4 \ + $GIT_VALGRIND_OPTIONS \ + "$GIT_VALGRIND"/../../"$base" "$@" -- 1.6.1.243.g6c8bb35 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html