fix: release a thread's hazard slot instead of freeing it #3720
Workflow file for this run
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
| name: ci | |
| on: [push, pull_request] | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| # the default job timeout is six hours. twice in one day a run wedged | |
| # with zero output inside the memcheck step's apt-get preamble (a | |
| # mirror stall), and each time it sat until someone noticed — the run | |
| # for #811 burned four hours. a wedged run should fail in minutes. | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: build | |
| run: cargo build --release | |
| - name: check rust crash guards | |
| run: make check-no-panics | |
| - name: rust unit tests | |
| run: cargo test --release --workspace --locked | |
| - name: cycle gc world-stop tests | |
| run: make test-cycle-gc | |
| - name: test | |
| run: | | |
| ./target/release/pith run tests/cases/test_suite.pith | |
| ./target/release/pith run tests/cases/test_process_command.pith | |
| ./target/release/pith run tests/cases/test_http_request_bytes.pith | |
| - name: run examples (native smoke) | |
| run: | | |
| ./target/release/pith run examples/hello.pith >/dev/null | |
| ./target/release/pith run examples/collection_methods.pith >/dev/null | |
| ./target/release/pith run examples/string_collection_methods.pith >/dev/null | |
| ./target/release/pith run examples/stdlib_algo.pith >/dev/null | |
| - name: green-thread runtime tests | |
| run: make green-tests | |
| - name: regression corpus under green | |
| run: make verify-green-corpus-only | |
| # the runner is linux, so every other step above already runs green by | |
| # default. this is the only step that exercises the PITH_GREEN=0 opt-out | |
| # across the corpus. | |
| - name: regression corpus under os threads | |
| run: make verify-osthread-corpus-only | |
| # the memcheck step below runs with valgrind's leak check off, because | |
| # the runtime's freelists and pools are still reachable at exit and | |
| # would bury a real signal. this covers leaks instead, by measuring | |
| # growth across two round counts. | |
| - name: leak growth | |
| run: make leak-check-only | |
| - name: build self-hosted compiler | |
| run: make self-host | |
| - name: run examples (self-hosted) | |
| run: make run-examples-self | |
| - name: native parity examples | |
| run: make parity-examples-only | |
| - name: sitegen golden check | |
| run: make sitegen-check | |
| - name: lsp golden check | |
| run: make lsp-check-only | |
| - name: logscan golden check | |
| run: make logscan-check | |
| - name: apic golden check | |
| run: make apic-check | |
| - name: parq golden check | |
| run: make parq-check | |
| - name: protogen golden check | |
| run: make protogen-check | |
| - name: docsite golden check | |
| run: make docsite-check | |
| - name: gzip interop check | |
| run: make gzip-interop-check | |
| - name: zstd interop check | |
| run: make zstd-interop-check | |
| - name: pure-pith zstd decoder interop | |
| run: make zstd-pure-check | |
| - name: pure-pith zstd encoder interop | |
| run: make zstd-encode-check | |
| - name: tls live interop (openssl) | |
| run: make tls-live-interop | |
| - name: tls interop (go crypto/tls) | |
| run: make tls-go-interop | |
| - name: tls interop (rustls) | |
| run: make tls-rustls-interop | |
| - name: fuzz check | |
| run: make fuzz-check | |
| - name: pithgen check | |
| run: make pithgen-check | |
| - name: memcheck | |
| # generous triple of the step's normal time (apt ~1min + the | |
| # curated suite ~8min): the observed wedges were apt-mirror stalls | |
| # that produced no output at all, so a hard cap converts hours of | |
| # silence into a fast, visible failure. | |
| timeout-minutes: 30 | |
| run: | | |
| # not `|| true`: `make memcheck` skips itself when valgrind is | |
| # missing, so a swallowed install failure would turn this step into a | |
| # guard that passes without running. | |
| # | |
| # install valgrind with a hard wall-clock bound and a retry. the | |
| # Acquire::*::Timeout options only bound an HTTP read, but the stalls | |
| # seen in practice hung before that layer (dns, the dpkg lock, sudo | |
| # itself) and sat until the step timeout with zero output. wrapping | |
| # each apt call in `timeout` fails fast wherever it wedges, and a | |
| # second attempt after a short sleep clears a transiently bad mirror. | |
| install_valgrind() { | |
| timeout 240 sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 update -qq \ | |
| && timeout 240 sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 install -y -qq valgrind | |
| } | |
| install_valgrind || { echo "apt install stalled or failed; retrying once after 15s"; sleep 15; install_valgrind; } | |
| make memcheck | |
| - name: verify a fresh clone can bootstrap from the seed | |
| run: make smoke-bootstrap-seed | |
| - name: verify the tracked seed matches the emitter source | |
| run: make check-bootstrap-seed | |
| - name: verify bootstrap fixed point | |
| run: make bootstrap-verify | |
| - name: lint | |
| run: | | |
| # std/ is in here because its public api IS the documentation — | |
| # docsite generates from it, so a naming slip there ships to | |
| # readers rather than staying an internal wart. | |
| # | |
| # lint now fails on a WARNING, not only on a hard error. a file | |
| # that declares itself generated in its leading comment block is | |
| # skipped, since generated code mirrors the naming of whatever | |
| # produced it and is not ours to rename. | |
| # | |
| # tools/docsite/sample is golden-test INPUT rather than source: | |
| # docsite renders that tree and the output is diffed, so the | |
| # fixture deliberately contains an undocumented public function | |
| # to pin how an undocumented item renders. documenting it would | |
| # delete the case it exists to cover. a marker comment is no | |
| # good either — the file's leading `##` block IS the module doc | |
| # the golden captures. | |
| for f in $(find examples self-host std tools -name '*.pith' \ | |
| -not -path 'tools/docsite/sample/*' | sort); do | |
| ./self-host/pith_main lint "$f" | |
| if [ $? -ne 0 ]; then | |
| echo "FAIL lint $f" | |
| exit 1 | |
| fi | |
| done | |
| - name: check examples (self-hosted) | |
| run: | | |
| for f in $(find examples -name '*.pith' | sort); do | |
| result=$(./self-host/pith_main check "$f" 2>&1) | |
| if [ "$result" != "ok" ]; then | |
| echo "FAIL $f (self-hosted check)" | |
| echo "$result" | |
| exit 1 | |
| fi | |
| echo "ok $f" | |
| done | |
| - name: check pith formatting | |
| run: | | |
| # std/ nests to std/net/http2, deeper than a `std/**/*.pith` glob | |
| # reaches without globstar, so the file list comes from find. | |
| for f in $(find self-host std tools bench -name '*.pith' | sort); do | |
| ./self-host/pith_main fmt --check "$f" | |
| if [ $? -ne 0 ]; then | |
| echo "FAIL $f not formatted" | |
| exit 1 | |
| fi | |
| done | |
| - name: check doc coverage | |
| run: | | |
| # std/ nests to std/net/http2, deeper than a `std/**/*.pith` glob | |
| # reaches without globstar, so the file list comes from find. | |
| # | |
| # self-host/ joined this gate once its pub items were documented. | |
| # note the gate and lint's E304 cover DIFFERENT things and neither | |
| # subsumes the other: this walks top-level items including structs, | |
| # E304 also walks impl methods. a file can pass here and still warn. | |
| for f in $(find self-host std -name '*.pith' | sort); do | |
| ./self-host/pith_main doc --check "$f" | |
| if [ $? -ne 0 ]; then | |
| echo "FAIL $f missing doc comments" | |
| exit 1 | |
| fi | |
| done |