Fix use of async_mutex guard to avoid coroutine RAII bug on GCC 15, r… #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # Copyright (c) 2026 Sam Darwin | |
| # Copyright (c) 2026 Michael Vandeberg | |
| # Copyright (c) 2026 Alexander Grund | |
| # | |
| # Distributed under the Boost Software License, Version 1.0. (See accompanying | |
| # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
| # | |
| # Official repository: https://github.com/cppalliance/corosio/ | |
| # | |
| # Instructions | |
| # | |
| # After running this workflow successfully, go to https://github.com/cppalliance/corosio/settings/pages | |
| # and enable github pages on the code-coverage branch. | |
| # The coverage will be hosted at https://cppalliance.org/corosio | |
| # | |
| name: Code Coverage | |
| on: | |
| push: | |
| branches: | |
| - master | |
| - develop | |
| paths: | |
| - 'src/**' | |
| - 'include/**' | |
| - '.github/workflows/code-coverage.yml' | |
| workflow_dispatch: | |
| concurrency: | |
| group: code-coverage-pages | |
| cancel-in-progress: false | |
| env: | |
| GIT_FETCH_JOBS: 8 | |
| NET_RETRY_COUNT: 5 | |
| GCOVR_COMMIT_MSG: "Update coverage data" | |
| BOOST_BRANCH_COVERAGE: 0 | |
| EXTRA_BOOST_LIBRARIES: "cppalliance/buffers cppalliance/capy cppalliance/http" | |
| jobs: | |
| build-linux: | |
| defaults: | |
| run: | |
| shell: bash | |
| name: Coverage (Linux) | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Install Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Install Python packages | |
| run: pip install gcovr | |
| - name: Checkout ci-automation | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: cppalliance/ci-automation | |
| path: ci-automation | |
| - name: Build and run tests & collect coverage data | |
| run: | | |
| set -xe | |
| ls -al | |
| export ORGANIZATION=${GITHUB_REPOSITORY_OWNER} | |
| export REPONAME=$(basename ${GITHUB_REPOSITORY}) | |
| export B2_CXXSTD=20 | |
| ./ci-automation/scripts/lcov-jenkins-gcc-13.sh --only-gcovr | |
| - name: Generate badges | |
| run: python3 ci-automation/scripts/generate_badges.py gcovr | |
| - name: Upload coverage artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-linux | |
| path: gcovr/ | |
| build-macos: | |
| defaults: | |
| run: | |
| shell: bash | |
| name: Coverage (macOS) | |
| runs-on: macos-15 | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Clone Boost.Corosio | |
| uses: actions/checkout@v6 | |
| with: | |
| path: corosio-root | |
| - name: Setup C++ | |
| uses: alandefreitas/cpp-actions/setup-cpp@v1.9.0 | |
| id: setup-cpp | |
| with: | |
| compiler: apple-clang | |
| version: '*' | |
| check-latest: true | |
| - name: Create vcpkg.json (macOS) | |
| run: | | |
| cat > corosio-root/vcpkg.json << 'EOF' | |
| { | |
| "name": "boost-corosio-deps", | |
| "version": "1.0.0", | |
| "dependencies": ["wolfssl"] | |
| } | |
| EOF | |
| - name: Setup vcpkg | |
| uses: lukka/run-vcpkg@v11 | |
| with: | |
| vcpkgDirectory: ${{ github.workspace }}/vcpkg | |
| vcpkgGitCommitId: bd52fac7114fdaa2208de8dd1227212a6683e562 | |
| vcpkgJsonGlob: '**/corosio-root/vcpkg.json' | |
| runVcpkgInstall: true | |
| - name: Set vcpkg paths (macOS) | |
| run: | | |
| set -xe | |
| if [[ "$(uname -m)" == "arm64" ]]; then | |
| triplet="arm64-osx" | |
| else | |
| triplet="x64-osx" | |
| fi | |
| echo "Using triplet: ${triplet}" | |
| vcpkg_installed=$(find "${{ github.workspace }}" -type d -name "${triplet}" -path "*/vcpkg_installed/*" | head -1) | |
| if [ -z "$vcpkg_installed" ]; then | |
| echo "ERROR: Could not find vcpkg_installed directory for triplet ${triplet}" | |
| find "${{ github.workspace }}" -type d -name "vcpkg_installed" 2>/dev/null || true | |
| exit 1 | |
| fi | |
| echo "vcpkg_installed=${vcpkg_installed}" | |
| echo "CMAKE_WOLFSSL_INCLUDE=${vcpkg_installed}/include" >> $GITHUB_ENV | |
| echo "CMAKE_WOLFSSL_LIBRARY=${vcpkg_installed}/lib/libwolfssl.a" >> $GITHUB_ENV | |
| - name: Clone Capy | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: cppalliance/capy | |
| ref: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} | |
| path: capy-root | |
| - name: Clone Boost | |
| uses: alandefreitas/cpp-actions/boost-clone@v1.9.0 | |
| id: boost-clone | |
| with: | |
| branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} | |
| boost-dir: boost-source | |
| modules-exclude-paths: '' | |
| scan-modules-dir: corosio-root | |
| scan-modules-ignore: corosio,capy | |
| - name: Patch Boost | |
| id: patch | |
| run: | | |
| set -xe | |
| module=${GITHUB_REPOSITORY#*/} | |
| echo "module=$module" >> $GITHUB_OUTPUT | |
| workspace_root=$(echo "$GITHUB_WORKSPACE" | sed 's/\\/\//g') | |
| echo -E "workspace_root=$workspace_root" >> $GITHUB_OUTPUT | |
| rm -r "boost-source/libs/$module" || true | |
| rm -r "boost-source/libs/capy" || true | |
| cd boost-source | |
| if git sparse-checkout list > /dev/null 2>&1; then | |
| echo "Disabling sparse checkout..." | |
| git sparse-checkout disable | |
| echo "Fetching any missing objects..." | |
| git fetch origin --no-tags | |
| git checkout | |
| fi | |
| cd .. | |
| cp -rL boost-source boost-root | |
| cd boost-root | |
| boost_root="$(pwd)" | |
| boost_root=$(echo "$boost_root" | sed 's/\\/\//g') | |
| echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT | |
| cp -r "$workspace_root"/corosio-root "libs/$module" | |
| cp -r "$workspace_root"/capy-root "libs/capy" | |
| - name: Build with coverage | |
| uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0 | |
| with: | |
| source-dir: boost-root | |
| build-dir: __build_cmake_test__ | |
| build-type: Debug | |
| build-target: tests | |
| run-tests: true | |
| install-prefix: .local | |
| cxxstd: '20' | |
| cc: ${{ steps.setup-cpp.outputs.cc || 'clang' }} | |
| cxx: ${{ steps.setup-cpp.outputs.cxx || 'clang++' }} | |
| cxxflags: '--coverage' | |
| ccflags: '--coverage' | |
| shared: false | |
| cmake-version: '>=3.20' | |
| extra-args: | | |
| -D Boost_VERBOSE=ON | |
| -D BOOST_INCLUDE_LIBRARIES="${{ steps.patch.outputs.module }}" | |
| -D CMAKE_EXPORT_COMPILE_COMMANDS=ON | |
| ${{ env.CMAKE_WOLFSSL_INCLUDE && format('-D WolfSSL_INCLUDE_Dir={0}', env.CMAKE_WOLFSSL_INCLUDE) || '' }} | |
| ${{ env.CMAKE_WOLFSSL_LIBRARY && format('-D WolfSSL_LIBRARY={0}', env.CMAKE_WOLFSSL_LIBRARY) || '' }} | |
| package: false | |
| package-artifact: false | |
| ref-source-dir: boost-root/libs/corosio | |
| - name: Install Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Install Python packages | |
| run: pip install gcovr | |
| - name: Checkout ci-automation | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: cppalliance/ci-automation | |
| path: ci-automation | |
| - name: Generate gcovr report | |
| run: | | |
| set -xe | |
| module=$(basename ${GITHUB_REPOSITORY}) | |
| mkdir -p gcovr | |
| # First pass: collect raw coverage data into JSON | |
| gcovr \ | |
| --root boost-root \ | |
| --gcov-executable "xcrun llvm-cov gcov" \ | |
| --merge-mode-functions separate \ | |
| --sort uncovered-percent \ | |
| --html-title "${module}" \ | |
| --merge-lines \ | |
| --exclude-unreachable-branches \ | |
| --exclude-throw-branches \ | |
| --exclude '.*/extra/.*' \ | |
| --exclude '.*/example/.*' \ | |
| --exclude '.*/examples/.*' \ | |
| --filter ".*/${module}/.*" \ | |
| --html --output gcovr/index.html \ | |
| --json-summary-pretty --json-summary gcovr/summary.json \ | |
| --json gcovr/coverage-raw.json \ | |
| boost-root/__build_cmake_test__ | |
| # Fix paths for repo-relative display | |
| python3 ci-automation/scripts/fix_paths.py \ | |
| gcovr/coverage-raw.json \ | |
| gcovr/coverage-fixed.json \ | |
| --repo "${module}" | |
| # Create symlinks so gcovr can find source files at repo-relative paths | |
| ln -sfn "boost-root/libs/${module}/include" include 2>/dev/null || true | |
| ln -sfn "boost-root/libs/${module}/src" src 2>/dev/null || true | |
| # Second pass: generate nested HTML from fixed JSON with custom templates | |
| gcovr \ | |
| -a gcovr/coverage-fixed.json \ | |
| --merge-mode-functions separate \ | |
| --sort uncovered-percent \ | |
| --html-nested \ | |
| --html-template-dir=ci-automation/gcovr-templates/html \ | |
| --html-title "${module}" \ | |
| --merge-lines \ | |
| --exclude-unreachable-branches \ | |
| --exclude-throw-branches \ | |
| --exclude '(^|.*/)test/.*' \ | |
| --exclude '.*/extra/.*' \ | |
| --exclude '.*/example/.*' \ | |
| --exclude '.*/examples/.*' \ | |
| --html --output gcovr/index.html \ | |
| --json-summary-pretty --json-summary gcovr/summary.json | |
| - name: Generate sidebar navigation | |
| run: python3 ci-automation/scripts/gcovr_build_tree.py gcovr | |
| - name: Generate badges | |
| run: python3 ci-automation/scripts/generate_badges.py gcovr --json gcovr/summary.json | |
| - name: Upload coverage artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-macos | |
| path: gcovr/ | |
| build-windows: | |
| defaults: | |
| run: | |
| shell: bash | |
| name: Coverage (Windows) | |
| runs-on: windows-2022 | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Clone Boost.Corosio | |
| uses: actions/checkout@v6 | |
| with: | |
| path: corosio-root | |
| - name: Setup C++ | |
| uses: alandefreitas/cpp-actions/setup-cpp@v1.9.0 | |
| id: setup-cpp | |
| with: | |
| compiler: mingw | |
| version: '*' | |
| check-latest: true | |
| - name: Install OpenSSL (MinGW) | |
| run: | | |
| C:/msys64/usr/bin/pacman.exe -S --noconfirm mingw-w64-x86_64-openssl | |
| echo "C:/msys64/mingw64/bin" >> $GITHUB_PATH | |
| - name: Create vcpkg.json | |
| run: | | |
| cat > corosio-root/vcpkg.json << 'EOF' | |
| { | |
| "name": "boost-corosio-deps", | |
| "version": "1.0.0", | |
| "dependencies": [ | |
| { "name": "wolfssl", "default-features": false } | |
| ] | |
| } | |
| EOF | |
| - name: Setup vcpkg | |
| uses: lukka/run-vcpkg@v11 | |
| env: | |
| VCPKG_DEFAULT_TRIPLET: x64-mingw-static | |
| with: | |
| vcpkgDirectory: ${{ github.workspace }}/vcpkg | |
| vcpkgGitCommitId: bd52fac7114fdaa2208de8dd1227212a6683e562 | |
| vcpkgJsonGlob: '**/corosio-root/vcpkg.json' | |
| runVcpkgInstall: true | |
| - name: Set vcpkg paths (Windows MinGW) | |
| run: | | |
| set -xe | |
| triplet="x64-mingw-static" | |
| vcpkg_installed=$(find "${{ github.workspace }}" -type d -name "${triplet}" -path "*/vcpkg_installed/*" | head -1) | |
| if [ -z "$vcpkg_installed" ]; then | |
| echo "ERROR: Could not find vcpkg_installed directory for triplet ${triplet}" | |
| find "${{ github.workspace }}" -type d -name "vcpkg_installed" 2>/dev/null || true | |
| exit 1 | |
| fi | |
| echo "vcpkg_installed=${vcpkg_installed}" | |
| echo "CMAKE_WOLFSSL_INCLUDE=${vcpkg_installed}/include" >> $GITHUB_ENV | |
| echo "CMAKE_WOLFSSL_LIBRARY=${vcpkg_installed}/lib/libwolfssl.a" >> $GITHUB_ENV | |
| echo "CMAKE_OPENSSL_ROOT=C:/msys64/mingw64" >> $GITHUB_ENV | |
| - name: Clone Capy | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: cppalliance/capy | |
| ref: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} | |
| path: capy-root | |
| - name: Clone Boost | |
| uses: alandefreitas/cpp-actions/boost-clone@v1.9.0 | |
| id: boost-clone | |
| with: | |
| branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} | |
| boost-dir: boost-source | |
| modules-exclude-paths: '' | |
| scan-modules-dir: corosio-root | |
| scan-modules-ignore: corosio,capy | |
| - name: Patch Boost | |
| id: patch | |
| run: | | |
| set -xe | |
| module=${GITHUB_REPOSITORY#*/} | |
| echo "module=$module" >> $GITHUB_OUTPUT | |
| workspace_root=$(echo "$GITHUB_WORKSPACE" | sed 's/\\/\//g') | |
| echo -E "workspace_root=$workspace_root" >> $GITHUB_OUTPUT | |
| rm -r "boost-source/libs/$module" || true | |
| rm -r "boost-source/libs/capy" || true | |
| cd boost-source | |
| if git sparse-checkout list > /dev/null 2>&1; then | |
| echo "Disabling sparse checkout..." | |
| git sparse-checkout disable | |
| echo "Fetching any missing objects..." | |
| git fetch origin --no-tags | |
| git checkout | |
| fi | |
| cd .. | |
| cp -rL boost-source boost-root | |
| cd boost-root | |
| boost_root="$(pwd)" | |
| boost_root=$(echo "$boost_root" | sed 's/\\/\//g') | |
| echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT | |
| cp -r "$workspace_root"/corosio-root "libs/$module" | |
| cp -r "$workspace_root"/capy-root "libs/capy" | |
| - name: Build with coverage | |
| uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0 | |
| with: | |
| source-dir: boost-root | |
| build-dir: __build_cmake_test__ | |
| generator: 'MinGW Makefiles' | |
| build-type: Debug | |
| build-target: tests | |
| run-tests: true | |
| install-prefix: .local | |
| cxxstd: '20' | |
| cc: ${{ steps.setup-cpp.outputs.cc || 'gcc' }} | |
| cxx: ${{ steps.setup-cpp.outputs.cxx || 'g++' }} | |
| cxxflags: '--coverage -fprofile-arcs -ftest-coverage -fprofile-update=atomic' | |
| ccflags: '--coverage -fprofile-arcs -ftest-coverage -fprofile-update=atomic' | |
| shared: false | |
| cmake-version: '>=3.20' | |
| extra-args: | | |
| -D Boost_VERBOSE=ON | |
| -D BOOST_INCLUDE_LIBRARIES="${{ steps.patch.outputs.module }}" | |
| -D CMAKE_EXPORT_COMPILE_COMMANDS=ON | |
| ${{ env.CMAKE_WOLFSSL_INCLUDE && format('-D WolfSSL_INCLUDE_Dir={0}', env.CMAKE_WOLFSSL_INCLUDE) || '' }} | |
| ${{ env.CMAKE_WOLFSSL_LIBRARY && format('-D WolfSSL_LIBRARY={0}', env.CMAKE_WOLFSSL_LIBRARY) || '' }} | |
| ${{ env.CMAKE_OPENSSL_ROOT && format('-D OPENSSL_ROOT_DIR={0}', env.CMAKE_OPENSSL_ROOT) || '' }} | |
| package: false | |
| package-artifact: false | |
| ref-source-dir: boost-root/libs/corosio | |
| - name: Install Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Install Python packages | |
| run: pip install gcovr | |
| - name: Checkout ci-automation | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: cppalliance/ci-automation | |
| path: ci-automation | |
| - name: Generate gcovr report | |
| env: | |
| PYTHONUTF8: 1 | |
| run: | | |
| set -xe | |
| module=$(basename ${GITHUB_REPOSITORY}) | |
| mkdir -p gcovr | |
| # First pass: collect raw coverage data into JSON | |
| gcovr \ | |
| --root boost-root \ | |
| --merge-mode-functions separate \ | |
| --sort uncovered-percent \ | |
| --html-title "${module}" \ | |
| --merge-lines \ | |
| --exclude-unreachable-branches \ | |
| --exclude-throw-branches \ | |
| --exclude '.*/extra/.*' \ | |
| --exclude '.*/example/.*' \ | |
| --exclude '.*/examples/.*' \ | |
| --filter ".*/${module}/.*" \ | |
| --html --output gcovr/index.html \ | |
| --json-summary-pretty --json-summary gcovr/summary.json \ | |
| --json gcovr/coverage-raw.json \ | |
| boost-root/__build_cmake_test__ | |
| # Fix paths for repo-relative display | |
| python3 ci-automation/scripts/fix_paths.py \ | |
| gcovr/coverage-raw.json \ | |
| gcovr/coverage-fixed.json \ | |
| --repo "${module}" | |
| # Create symlinks so gcovr can find source files at repo-relative paths | |
| ln -sfn "boost-root/libs/${module}/include" include 2>/dev/null || true | |
| ln -sfn "boost-root/libs/${module}/src" src 2>/dev/null || true | |
| # Second pass: generate nested HTML from fixed JSON with custom templates | |
| gcovr \ | |
| -a gcovr/coverage-fixed.json \ | |
| --merge-mode-functions separate \ | |
| --sort uncovered-percent \ | |
| --html-nested \ | |
| --html-template-dir=ci-automation/gcovr-templates/html \ | |
| --html-title "${module}" \ | |
| --merge-lines \ | |
| --exclude-unreachable-branches \ | |
| --exclude-throw-branches \ | |
| --exclude '(^|.*/)test/.*' \ | |
| --exclude '.*/extra/.*' \ | |
| --exclude '.*/example/.*' \ | |
| --exclude '.*/examples/.*' \ | |
| --html --output gcovr/index.html \ | |
| --json-summary-pretty --json-summary gcovr/summary.json | |
| - name: Generate sidebar navigation | |
| run: python3 ci-automation/scripts/gcovr_build_tree.py gcovr | |
| - name: Generate badges | |
| run: python3 ci-automation/scripts/generate_badges.py gcovr --json gcovr/summary.json | |
| - name: Upload coverage artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-windows | |
| path: gcovr/ | |
| deploy: | |
| needs: [build-linux, build-macos, build-windows] | |
| if: ${{ !cancelled() }} | |
| defaults: | |
| run: | |
| shell: bash | |
| name: Deploy Coverage | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Check for code-coverage Branch | |
| run: | | |
| set -xe | |
| git config --global user.name cppalliance-bot | |
| git config --global user.email cppalliance-bot@example.com | |
| git fetch origin | |
| if git branch -r | grep origin/code-coverage; then | |
| echo "The code-coverage branch exists. Continuing." | |
| else | |
| echo "The code-coverage branch does not exist. Creating it." | |
| git switch --orphan code-coverage | |
| git commit --allow-empty -m "$GCOVR_COMMIT_MSG" | |
| git push origin code-coverage | |
| git checkout $GITHUB_REF_NAME | |
| fi | |
| - name: Checkout GitHub pages branch | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: code-coverage | |
| path: gh_pages_dir | |
| - name: Download coverage artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: coverage-* | |
| path: coverage-artifacts/ | |
| - name: Copy coverage results | |
| run: | | |
| set -xe | |
| touch gh_pages_dir/.nojekyll | |
| mkdir -p "gh_pages_dir/develop" | |
| mkdir -p "gh_pages_dir/master" | |
| # Remove old single-platform directory (migration from gcovr/ to gcovr-linux/) | |
| rm -rf "gh_pages_dir/${GITHUB_REF_NAME}/gcovr" | |
| # Copy each platform's results (only if artifact exists) | |
| for platform in linux macos windows; do | |
| if [ -d "coverage-artifacts/coverage-${platform}" ]; then | |
| rm -rf "gh_pages_dir/${GITHUB_REF_NAME}/gcovr-${platform}" | |
| cp -rp "coverage-artifacts/coverage-${platform}" \ | |
| "gh_pages_dir/${GITHUB_REF_NAME}/gcovr-${platform}" | |
| fi | |
| done | |
| # Generate branch index pages | |
| for branch in develop master; do | |
| cat > "gh_pages_dir/${branch}/index.html" << 'HTMLEOF' | |
| <html> | |
| <head><title>Code Coverage</title></head> | |
| <body> | |
| <h2>Code Coverage Reports</h2> | |
| <ul> | |
| <li><a href="gcovr-linux/index.html">Linux (epoll)</a></li> | |
| <li><a href="gcovr-macos/index.html">macOS (kqueue)</a></li> | |
| <li><a href="gcovr-windows/index.html">Windows (IOCP)</a></li> | |
| </ul> | |
| </body> | |
| </html> | |
| HTMLEOF | |
| done | |
| # Root index | |
| cat > gh_pages_dir/index.html << 'HTMLEOF' | |
| <html> | |
| <head></head> | |
| <body> | |
| <a href="develop/index.html">develop</a><br> | |
| <a href="master/index.html">master</a><br> | |
| </body> | |
| </html> | |
| HTMLEOF | |
| cd gh_pages_dir | |
| git add . | |
| git commit --amend -m "$GCOVR_COMMIT_MSG" | |
| git push -f origin code-coverage |