diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 901924f1d..662b7a74f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -45,6 +45,12 @@ jobs: strategy: matrix: py-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + # Make sure we can build and run tests on an instrumented build that uses libasan + # We aren't necessarily checking for memory errors / leaks in this test + sanitizer: [false] + include: + - py-version: 3.8 + sanitizer: true fail-fast: false steps: @@ -64,15 +70,23 @@ jobs: - name: Install build dependencies (pip packages) run: python3 -m pip install -r requirements.txt + - if: ${{ matrix.sanitizer }} + run: echo SANITIZER=1 >> $GITHUB_ENV + - name: Build client run: python3 -m build env: CFLAGS: '-Werror' + - run: echo WHEEL_GH_ARTIFACT_NAME=wheel-${{ matrix.py-version }} >> $GITHUB_ENV + + - if: ${{ matrix.sanitizer }} + run: echo WHEEL_GH_ARTIFACT_NAME=${{ env.WHEEL_GH_ARTIFACT_NAME }}-sanitizer >> $GITHUB_ENV + - name: Send wheel to test jobs uses: actions/upload-artifact@v3 with: - name: wheel-${{ matrix.py-version }} + name: ${{ env.WHEEL_GH_ARTIFACT_NAME }} path: ./dist/*.whl generate-coverage-report: @@ -259,6 +273,10 @@ jobs: "3.12", "3.13" ] + sanitizer: [false] + include: + - py-version: 3.8 + sanitizer: true fail-fast: false steps: @@ -271,9 +289,14 @@ jobs: python-version: ${{ matrix.py-version }} architecture: 'x64' + - run: echo WHEEL_GH_ARTIFACT_NAME=wheel-${{ matrix.py-version }} >> $GITHUB_ENV + + - if: ${{ matrix.sanitizer }} + run: echo WHEEL_GH_ARTIFACT_NAME=${{ env.WHEEL_GH_ARTIFACT_NAME }}-sanitizer >> $GITHUB_ENV + - uses: actions/download-artifact@v3 with: - name: wheel-${{ matrix.py-version }} + name: ${{ env.WHEEL_GH_ARTIFACT_NAME }} - name: Install client run: pip install *.whl @@ -303,6 +326,11 @@ jobs: with: container-name: aerospike + - if: ${{ matrix.sanitizer }} + run: | + echo ASAN_OPTIONS='halt_on_error=0' >> $GITHUB_ENV + echo LD_PRELOAD=$(gcc --print-file-name=libasan.so) >> $GITHUB_ENV + - name: Run tests run: python -m pytest ./new_tests -vv working-directory: test diff --git a/BUILD.md b/BUILD.md index 61504b29a..baa740de6 100644 --- a/BUILD.md +++ b/BUILD.md @@ -170,6 +170,8 @@ Then once you install the build with sanitizer, you may run a Python script usin LD_PRELOAD=/lib/x86_64-linux-gnu/libasan.so.6 python3 -c "import aerospike" ``` +This is only supported for building with GCC. + ### Troubleshooting macOS In some versions of macOS, Python 2.7 is installed as ``python`` with diff --git a/custom-versionit-format.py b/custom-versionit-format.py index 195eedcbf..6551d0963 100644 --- a/custom-versionit-format.py +++ b/custom-versionit-format.py @@ -58,5 +58,7 @@ def my_format( version_str = append_to_local(version_str, "unoptimized") if os.getenv("INCLUDE_DSYM"): version_str = append_to_local(version_str, "dsym") + if os.getenv("SANITIZER"): + version_str = append_to_local(version_str, "sanitizer") return version_str diff --git a/setup.py b/setup.py index 78513f45d..567b41e60 100644 --- a/setup.py +++ b/setup.py @@ -87,14 +87,16 @@ SANITIZER=os.getenv('SANITIZER') if SANITIZER: - sanitizer_flags = [ + sanitizer_c_and_ld_flags = [ '-fsanitize=address', - '-fsanitize-recover=all' + '-fno-omit-frame-pointer' ] - extra_compile_args.extend(sanitizer_flags) + sanitizer_cflags = sanitizer_c_and_ld_flags.copy() + sanitizer_cflags.append('-fsanitize-recover=all') + extra_compile_args.extend(sanitizer_cflags) - extra_link_args.append("-static-libasan") - extra_link_args.extend(sanitizer_flags) + sanitizer_ldflags = sanitizer_c_and_ld_flags.copy() + extra_link_args.extend(sanitizer_ldflags) library_dirs = ['/usr/local/opt/openssl/lib', '/usr/local/lib'] libraries = [ @@ -232,6 +234,11 @@ def clean(): ] if UNOPTIMIZED: cmd.append('O=0') + if SANITIZER: + ext_cflags = " ".join(sanitizer_cflags) + cmd.append(f"EXT_CFLAGS={ext_cflags}") + ldflags = " ".join(sanitizer_ldflags) + cmd.append(f"LDFLAGS={ldflags}") def compile(): print(cmd, library_dirs, libraries)