name: '🧵 ThreadSanitizer' # Reusable workflow: builds the channel stress suite with ThreadSanitizer and # runs it. This is the dynamic half of verifying the lock-free SPSC Channel # (the static half is the CDSChecker model-check harness in verify/). # # Triggering and path filtering are owned by ci.yaml (the orchestrator), which # calls this only when code changed. workflow_dispatch is kept for manual runs. # # Runs in the prebuilt builder image (gcc:14), which already ships libtsan — no # package installs at job time. on: workflow_call: workflow_dispatch: jobs: tsan: runs-on: linux/amd64 container: image: gitea.tourolle.paris/dtourolle/kpnpp-builder:latest steps: - name: Checkout repository uses: actions/checkout@v4 with: path: tsan-${{ github.run_id }} - name: Cache FetchContent dependencies uses: actions/cache@v3 with: path: ~/.cmake/fetchcontent key: cmake-fetchcontent-${{ hashFiles('**/CMakeLists.txt') }} restore-keys: cmake-fetchcontent- - name: Configure (TSan) working-directory: tsan-${{ github.run_id }} run: | cmake -S . -B build \ -G Ninja \ -DCMAKE_BUILD_TYPE=Debug \ -DKPN_SANITIZER=thread \ -DKPN_BUILD_TESTS=ON \ -DKPN_BUILD_EXAMPLES=OFF \ -DKPN_BUILD_PYTHON=OFF \ -DFETCHCONTENT_BASE_DIR=$HOME/.cmake/fetchcontent - name: Build (TSan) working-directory: tsan-${{ github.run_id }} run: cmake --build build --parallel --target kpn_tests kpn_tests_stress - name: Run stress suite under TSan working-directory: tsan-${{ github.run_id }} # halt_on_error=1 makes the first detected race fail the job; the report # (with both stacks) is printed to the log. second_deadlock_stack gives # the full picture for lock-order issues. env: TSAN_OPTIONS: "halt_on_error=1 second_deadlock_stack=1" run: ./build/tests/kpn_tests_stress - name: Run unit tests under TSan working-directory: tsan-${{ github.run_id }} env: TSAN_OPTIONS: "halt_on_error=1 second_deadlock_stack=1" run: ./build/tests/kpn_tests - name: Cleanup if: always() run: rm -rf tsan-${{ github.run_id }}