Skip to content

0.3.4 — cancel a request in flight with a std::stop_token #68

0.3.4 — cancel a request in flight with a std::stop_token

0.3.4 — cancel a request in flight with a std::stop_token #68

Workflow file for this run

name: CI
# THE BUILD TOOL IS NAMED HERE AND NOWHERE ELSE.
#
# This workflow used to install it through `.xlings.json', a workspace pin that
# `actions/checkout' places in the working directory before anything else runs.
# Two consequences followed and neither was visible in a passing log:
#
# * every `mcpp' invocation in this repository resolved to the pinned version
# rather than to the one the job had installed, because that pin is read
# from the current directory;
# * the pin named 0.0.13, from 2026-05. The index no longer serves the
# toolchain packages a build tool of that age asks for, so `mcpp build'
# ended at `package 'xim:glibc@>=2.39' not found' before compiling a line.
#
# The pin file is removed. The version is an environment variable, so the two
# places that need it, the install and the cache, cannot drift apart again.
on:
push:
branches: [master]
pull_request:
# A CANARY, BECAUSE THIS ROTTED WHERE NOTHING WOULD LOOK.
#
# The breakage above occurred between 2026-07-11 and 2026-08-29 and nothing
# reported it: master received no pushes in that window, so the first run to
# meet it was a contributor's pull request, whose author had no way to
# distinguish a broken environment from a broken change.
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:
env:
# 2026.9.30.2 and not earlier: 2026.9.28.3 refused x86_64-windows-musl
# ("cannot be built on this host") before the dependency graph that supplies
# its system side, openkal-llvm-runtime, had been resolved.
MCPP_VERSION: 2026.9.30.2
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
jobs:
# ── Linux, under both standard libraries ─────────────────────────────────────
#
# WHY TWO TOOLCHAINS. The job used to run whatever mcpp installed by default on
# a fresh runner, which is gcc and libstdc++, and nothing ran the tests under
# libc++. libc++ is the standard library of every other job below — macOS and
# openkal — and of mcpp's own default where a developer has chosen llvm; the
# cancellation tests met a libc++ defect that libstdc++ does not have
# (tests/test_cancel.cpp, at the top), and no job here could have seen it.
build:
name: build + test (linux x86_64, ${{ matrix.toolchain }})
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
toolchain: ['[email protected]', '[email protected]']
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
# --retry-all-errors and not --retry alone: the first covers a
# transient HTTP status and a timeout, and what this step actually
# meets is a failure of the transport. Observed in this ecosystem as
# `curl: (35) Recv failure: Connection reset by peer', thirteen
# seconds into a job, before anything was built.
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
# The version this job runs is the version it prints. A pin that is
# not read is the failure this file exists to stop repeating.
mcpp --version
# A runner outside China reaches the mirrors this names. The CN set is
# for a developer's machine and is slower or unreachable from here.
mcpp self config --mirror GLOBAL
# The toolchain mcpp bootstraps is decided by the version pinned above, so
# that version and the toolchain are the whole of the key.
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry
key: mcpp-sandbox-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }}-${{ matrix.toolchain }}
- name: Select the toolchain
run: |
spec='${{ matrix.toolchain }}'
mcpp toolchain install "${spec%@*}" "${spec#*@}"
mcpp toolchain default "$spec"
mcpp toolchain list
- name: Build with mcpp
run: mcpp build
# Most of these are hermetic: `test_framing` needs nothing, and `test_pool`,
# `test_proxy` and `test_cancel` script their own servers on 127.0.0.1. The
# eight in `test_download` and `test_resolver` reach httpbin.org and
# one.one.one.one; a network failure among them is distinguishable in the
# log by the endpoint it names.
- name: Run tests
run: mcpp test
# A TEMPLATE IS PART OF THE RELEASE THAT SHIPS IT, AND `mcpp new` CAN ONLY
# REACH ONE THAT IS ALREADY PUBLISHED. Checking them after the release
# makes the first person to run `mcpp new` the one who finds out they do
# not compile, so this renders them the way the scaffolder does and builds
# them against this commit. It has already caught one: `import std`
# carries no `stdout` macro, so a progress bar flushed through it did not
# compile in a generated project while compiling fine in this repository.
- name: Smoke-test the project templates
run: bash tools/template_smoke.sh
# ── macOS ────────────────────────────────────────────────────────────────────
#
# THE README NAMES macOS, AND UNTIL THIS JOB NOTHING RAN THERE. The
# differences are real and in this library's own code: SO_NOSIGPIPE rather
# than MSG_NOSIGNAL (src/platform.cppm), /dev/urandom as mbedTLS's entropy,
# the system CA bundle's location, and poll(2) on a socket whose connect is in
# progress, which the cancellation slices wait on.
macos:
name: build + test (macos arm64, [email protected])
runs-on: macos-15
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry
key: mcpp-sandbox-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }}[email protected]
- name: Select the toolchain
run: |
mcpp toolchain install llvm 22.1.8
mcpp toolchain default [email protected]
mcpp toolchain list
- name: Build with mcpp
run: mcpp build
- name: Run tests
run: mcpp test
# ── The same sources, on a different kernel ABI ──────────────────────────────
#
# WHY THIS IS A SEPARATE JOB AND NOT A STEP. It resolves a different toolchain
# (llvm rather than gcc) and a different everything below the program — musl
# ported onto openkal, libc++ configured for that musl, and openkal-linux
# beneath both. Sharing a job would mean sharing a cache key between two
# stacks that have nothing in common but the source tree.
#
# WHAT IT CATCHES THAT THE JOB ABOVE CANNOT. `Socket::write` sends with
# MSG_NOSIGNAL and `connect_addrinfo` sets SO_NOSIGPIPE, and which of those
# exists is decided by the C library rather than by the operating system —
# openkal-musl defines the first and not the second. A `#ifdef` that is wrong
# about that compiles cleanly here and fails there, which is exactly how
# 5e7d66f reached master.
#
# FOUR TARGETS, THE ONES mcpp-index MEASURES tinyhttps ON (its
# tests/openkal/pins.toml). aarch64-linux-musl runs under qemu, through the
# runner examples/openkal names. x86_64-windows-musl is built here and run on
# Windows itself by the job after this one: wine took anywhere from four to
# more than thirty minutes to install on these runners, and Windows is the
# system the program is for. The Windows target is where every handshake used
# to fail for want of entropy (src/tls.cppm); it has no name resolution, so its
# network step reports "no network" and the cancellation check, which needs
# none, is what runs.
openkal:
name: build + run (${{ matrix.target }}, above openkal)
runs-on: ubuntu-24.04
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
target: ['x86_64-linux-gnu', 'x86_64-linux-musl', 'x86_64-windows-musl', 'aarch64-linux-musl']
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Install the runner
if: matrix.target == 'aarch64-linux-musl'
timeout-minutes: 15
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq --no-install-recommends qemu-user > /dev/null
qemu-aarch64 --version | head -1
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry
key: mcpp-openkal-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }}-${{ matrix.target }}
# The example builds the library from this checkout (`path = "../.."`) and
# takes the stack beneath it from the index, so what is tested is this
# commit against the published openkal packages.
#
# The toolchain is named, as mcpp-index's measurement names it. A fresh
# runner's default is the gcc mcpp installed first, and with it
# x86_64-windows-musl was refused as "cannot be built on this host" even
# though the example's own `[toolchain]` names llvm, the one the openkal
# runtime supplies that target for.
#
# It cancels a handshake against a local listener, which needs no network,
# and then makes one HTTPS request; it reports "no network" rather than
# failing when there is none, so a runner without egress reports "not run"
# instead of "broken". A certificate the client refused is a failure, not
# an absence of network. The build, the link, the framing parsers and the
# cancellation are checked either way.
- name: Build and run above openkal
if: matrix.target != 'x86_64-windows-musl'
working-directory: examples/openkal
run: |
set -o pipefail
mcpp run --toolchain [email protected] --target '${{ matrix.target }}' 2>&1 | tee run.log
grep -q '^cancellation: ok' run.log
# A static PE executable that imports only system DLLs, so it runs on any
# Windows as it is.
- name: Build for Windows above openkal
if: matrix.target == 'x86_64-windows-musl'
working-directory: examples/openkal
run: |
mcpp build --toolchain [email protected] --target x86_64-windows-musl
mkdir -p "$RUNNER_TEMP/smoke"
cp target/x86_64-windows-musl/*/bin/smoke.exe "$RUNNER_TEMP/smoke/"
- uses: actions/upload-artifact@v4
if: matrix.target == 'x86_64-windows-musl'
with:
name: smoke-x86_64-windows-musl
path: ${{ runner.temp }}/smoke/smoke.exe
if-no-files-found: error
openkal-windows:
name: run (x86_64-windows-musl, above openkal, on Windows)
needs: openkal
runs-on: windows-2022
timeout-minutes: 15
defaults:
run:
shell: bash
steps:
- uses: actions/download-artifact@v4
with:
name: smoke-x86_64-windows-musl
# Above openkal the Windows certificate store is not read (README,
# "Platforms"), so the program is given a bundle: Git for Windows's, copied
# beside it, because openkal resolves a relative name against the working
# directory and names no absolute path.
- name: Run above openkal
run: |
set -o pipefail
cp "/c/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt" ca-bundle.crt
SSL_CERT_FILE=ca-bundle.crt ./smoke.exe 2>&1 | tee run.log
grep -q '^cancellation: ok' run.log
# ── Windows ──────────────────────────────────────────────────────────────────
#
# WHY THIS JOB EXISTS. Windows keeps no bundle file, so on a Windows Sockets
# build `load_ca_certs` reads the system's ROOT store through the Win32 API
# (src/ca_bundle.cppm). That code is compiled on no other platform, and a job
# elsewhere can show neither that it builds nor that the roots it returns
# verify a real certificate chain. `test_ca_store` asserts both.
#
# AND THE HERMETIC TESTS RUN HERE TOO. They script their own servers on
# 127.0.0.1, and Windows Sockets is where `poll` is `WSAPoll`, a connect in
# progress is reported differently, and the cancellation slices were never
# run before this job ran them.
windows:
name: build + test (windows x86_64, ${{ matrix.toolchain }})
runs-on: windows-2022
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
toolchain: ['msvc@system', '[email protected]']
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Install xlings
shell: pwsh
run: |
irm https://d2learn.org/xlings-install.ps1.txt | iex
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Select the toolchain
run: |
spec='${{ matrix.toolchain }}'
case "$spec" in
msvc*) mcpp toolchain default msvc ;;
*) mcpp toolchain install "${spec%@*}" "${spec#*@}"
mcpp toolchain default "$spec" ;;
esac
mcpp toolchain list
- name: The system store verifies a public chain
run: |
mcpp test test_ca_store 2>&1 | tee tests.log
grep -q '^test_ca_store \.\.\. ok' tests.log
- name: The hermetic tests
run: |
set -o pipefail
for t in test_framing test_tls_verify test_pool test_proxy test_cancel; do
mcpp test "$t" 2>&1 | tee "$t.log"
grep -q "^$t \.\.\. ok" "$t.log"
done