Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Valgrind build on debug Python 3.9 #2746

Merged
merged 8 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 44 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,30 +169,61 @@ jobs:
strategy:
fail-fast: false
matrix:
python:
- version: 3.9
debug: true
- version: 3.10-dev
debug: false
include:
- python-version: 3.9
python-debug: true
valgrind: true
- python-version: 3.10-dev
python-debug: false

name: "🐍 ${{ matrix.python.version }}${{ matrix.python.debug && ' (debug)' || '' }} • deadsnakes • x64"
name: "🐍 ${{ matrix.python-version }}${{ matrix.python-debug && '-dbg' || '' }} (deadsnakes)${{ matrix.valgrind && ' • Valgrind' || '' }} • x64"
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Setup Python ${{ matrix.python.version }} (deadsnakes)
- name: Setup Python ${{ matrix.python-version }} (deadsnakes)
uses: deadsnakes/action@v2.1.1
with:
python-version: ${{ matrix.python.version }}
debug: ${{ matrix.python.debug }}
python-version: ${{ matrix.python-version }}
debug: ${{ matrix.python-debug }}

- name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.6

- name: Valgrind cache
if: matrix.valgrind
uses: actions/cache@v2
id: cache-valgrind
with:
path: valgrind
key: 3.16.1 # Valgrind version

- name: Compile Valgrind
if: matrix.valgrind && steps.cache-valgrind.outputs.cache-hit != 'true'
run: |
VALGRIND_VERSION=3.16.1
curl https://sourceware.org/pub/valgrind/valgrind-$VALGRIND_VERSION.tar.bz2 -o - | tar xj
mv valgrind-$VALGRIND_VERSION valgrind
cd valgrind
./configure
make -j 2 > /dev/null

- name: Install Valgrind
if: matrix.valgrind
working-directory: valgrind
run: |
sudo make install
sudo apt-get update
sudo apt-get install libc6-dbg # Needed by Valgrind

- name: Prepare env
run: python -m pip install -r tests/requirements.txt --prefer-binary

- name: Configure
run: >
cmake -S . -B build
-DCMAKE_BUILD_TYPE=Debug
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
Expand All @@ -207,6 +238,10 @@ jobs:
- name: C++ tests
run: cmake --build build --target cpptest

- name: Run Valgrind on Python tests
if: matrix.valgrind
run: cmake --build build --target memcheck


# Testing on clang using the excellent silkeh clang docker images
clang:
Expand Down
30 changes: 28 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,17 @@ endif()
string(REPLACE "test_" "${CMAKE_CURRENT_SOURCE_DIR}/test_" PYBIND11_ABS_PYTEST_FILES
"${PYBIND11_PYTEST_FILES}")

set(PYBIND11_TEST_PREFIX_COMMAND
""
CACHE STRING "Put this before pytest, use for checkers and such")

# A single command to compile and run the tests
add_custom_target(
pytest
COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_ABS_PYTEST_FILES}
COMMAND ${PYBIND11_TEST_PREFIX_COMMAND} ${PYTHON_EXECUTABLE} -m pytest
${PYBIND11_ABS_PYTEST_FILES}
DEPENDS ${test_targets}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
USES_TERMINAL)

if(PYBIND11_TEST_OVERRIDE)
Expand All @@ -386,6 +391,27 @@ if(PYBIND11_TEST_OVERRIDE)
"Note: not all tests run: -DPYBIND11_TEST_OVERRIDE is in effect")
endif()

# cmake-format: off
add_custom_target(
memcheck
COMMAND
PYTHONMALLOC=malloc
valgrind
--leak-check=full
--show-leak-kinds=definite,indirect
--errors-for-leak-kinds=definite,indirect
--error-exitcode=1
--read-var-info=yes
--track-origins=yes
--suppressions="${CMAKE_CURRENT_SOURCE_DIR}/valgrind-python.supp"
--suppressions="${CMAKE_CURRENT_SOURCE_DIR}/valgrind-numpy-scipy.supp"
--gen-suppressions=all
${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_ABS_PYTEST_FILES}
DEPENDS ${test_targets}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
USES_TERMINAL)
# cmake-format: on

# Add a check target to run all the tests, starting with pytest (we add dependencies to this below)
add_custom_target(check DEPENDS pytest)

Expand Down
2 changes: 1 addition & 1 deletion tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ pytest==4.6.9; python_version<"3.5"
pytest==6.1.2; python_version=="3.5"
pytest==6.2.1; python_version>="3.6"
scipy==1.2.3; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version<"3.6"
scipy==1.5.2; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.6" and python_version<"3.9"
scipy==1.5.4; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.6" and python_version<"3.10"
3 changes: 1 addition & 2 deletions tests/test_virtual_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ def dispatch(self):
== 'Tried to call pure virtual function "Base::dispatch"'
)

p = PyClass1()
return m.dispatch_issue_go(p)
return m.dispatch_issue_go(PyClass1())

b = PyClass2()
assert m.dispatch_issue_go(b) == "Yay.."
Expand Down
118 changes: 118 additions & 0 deletions tests/valgrind-numpy-scipy.supp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Valgrind suppression file for NumPy & SciPy errors and leaks in pybind11 tests

{
Leaks when importing NumPy
Memcheck:Leak
fun:malloc
fun:_PyMem_RawMalloc
fun:PyObject_Malloc
fun:_PyObject_GC_Alloc
fun:_PyObject_GC_Malloc
fun:_PyObject_GC_NewVar
fun:tuple_alloc
fun:PyTuple_Pack
...
fun:__pyx_pymod_exec_*
}

{
Leaks when importing NumPy (bis)
Memcheck:Leak
fun:malloc
fun:_PyMem_RawMalloc
fun:PyObject_Malloc
fun:_PyObject_New
fun:PyCode_NewWithPosOnlyArgs
fun:PyCode_New
...
fun:__pyx_pymod_exec_*
}

{
Leaks when importing NumPy (tris)
Memcheck:Leak
fun:malloc
fun:_PyMem_RawMalloc
fun:PyObject_Malloc
fun:_PyObject_GC_Alloc
fun:_PyObject_GC_Malloc
fun:_PyObject_GC_NewVar
fun:tuple_alloc
fun:_PyTuple_FromArray
fun:_PyObject_MakeTpCall
fun:_PyObject_VectorcallTstate
fun:PyObject_Vectorcall
fun:call_function
fun:_PyEval_EvalFrameDefault
fun:_PyEval_EvalFrame
fun:function_code_fastcall
fun:_PyFunction_Vectorcall
}

{
Leaks when importing NumPy (quater)
Memcheck:Leak
fun:malloc
fun:_PyMem_RawMalloc
fun:PyObject_Malloc
fun:_PyObject_GC_Alloc
fun:_PyObject_GC_Malloc
fun:_PyObject_GC_NewVar
fun:tuple_alloc
fun:PyTuple_New
fun:r_object
fun:r_object
fun:r_object
fun:r_object
}

{
Leaks when importing NumPy (quinquies)
Memcheck:Leak
fun:malloc
fun:_PyMem_RawMalloc
fun:PyObject_Malloc
fun:_PyObject_GC_Alloc
fun:_PyObject_GC_Malloc
fun:_PyObject_GC_NewVar
fun:tuple_alloc
fun:PyTuple_New
fun:dictiter_iternextitem
fun:list_extend
fun:_PyList_Extend
fun:PySequence_List
}

{
Leak when importing scipy.fft
Memcheck:Leak
fun:_Znwm
fun:PyInit_pypocketfft
fun:_PyImport_LoadDynamicModuleWithSpec
fun:_imp_create_dynamic_impl.constprop.3
fun:_imp_create_dynamic
fun:cfunction_vectorcall_FASTCALL
fun:PyVectorcall_Call
fun:_PyObject_Call
fun:PyObject_Call
fun:do_call_core
fun:_PyEval_EvalFrameDefault
fun:_PyEval_EvalFrame
fun:_PyEval_EvalCode
}

{
NumPy leaks when spawning a subprocess
Memcheck:Leak
fun:malloc
...
fun:_buffer_get_info
fun:array_getbuffer
fun:PyObject_GetBuffer
fun:__Pyx__GetBufferAndValidate*
fun:__pyx_f_5numpy_6random_13bit_generator_12SeedSequence_mix_entropy
fun:__pyx_pw_5numpy_6random_13bit_generator_12SeedSequence_1__init__
fun:type_call
fun:__Pyx__PyObject_CallOneArg
fun:__pyx_pw_5numpy_6random_13bit_generator_12BitGenerator_1__init__
}
Loading