Repository navigation
Refine CI and build to compile/run C examples #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
6bdc8dd
Never claim the uninitialized idle job
jserv 499de68
Claim and publish the versioned queue head consistently
jserv 6b75673
Wait for the workers to park before destroying the pool
jserv 8728524
Drop the stale front link when the queue drains
jserv c969005
Align the idle job to a cache line
jserv ece0179
Clean up after a failed thread pool init
jserv 6c9b0c3
Free unclaimed futures when tearing the pool down
jserv 11c8f18
Report job failures through the exit status
jserv 094a52d
Make the ABA demonstration deterministic
jserv cb7a24b
Match the relaxed-ordering listing to the worker loop
jserv fe9b56d
Give each program its own make rule
jserv 194878d
Rebuild the PDF when an example changes
jserv e84c84e
Clean and ignore what the build generates
jserv f25132d
Explain how to build the examples
jserv 986b431
Move to current actions and make the cache usable
jserv d85ad4f
Add standalone scripts for the C checks
jserv 9a714cf
Build and run examples, and gate the release
jserv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #!/usr/bin/env bash | ||
| # Static analysis over the C examples. | ||
| # | ||
| # --enable=warning adds to the error-severity checks rather than selecting | ||
| # them: those always run. So this does not exempt the use-after-free the | ||
| # manuscript keeps on purpose, and no suppression is needed for it either. | ||
| # cppcheck does not see it, because the free and the stale read are in | ||
| # different threads rather than along one path through a function. Style and | ||
| # portability sweeps stay off, since those would report the deliberate | ||
| # defects the book is built around. | ||
| set -e -u -o pipefail | ||
|
|
||
| mapfile -t SOURCES < <(git ls-files -z -- 'examples/*.c' | tr '\0' '\n') | ||
|
|
||
| if [ ${#SOURCES[@]} -eq 0 ]; then | ||
| echo "No tracked C source files found." | ||
| exit 0 | ||
| fi | ||
|
|
||
| timeout 120 cppcheck \ | ||
| --platform=unix64 \ | ||
| --enable=warning \ | ||
| --max-configs=1 --error-exitcode=1 --inline-suppr \ | ||
| --suppress=checkersReport --suppress=unmatchedSuppression \ | ||
| --suppress=missingIncludeSystem --suppress=noValidConfiguration \ | ||
| --suppress=normalCheckLevelMaxBranches \ | ||
| --suppress=preprocessorErrorDirective \ | ||
| -D_GNU_SOURCE -D__linux__ \ | ||
| "${SOURCES[@]}" | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #!/usr/bin/env bash | ||
| # Verify clang-format conformance for the C examples the book embeds. | ||
| # | ||
| # The version is pinned because clang-format releases disagree about this | ||
| # style, and the examples are printed verbatim in the PDF: a reformat that | ||
| # only some contributors reproduce would churn the typeset listings. | ||
| set -e -u -o pipefail | ||
|
|
||
| if [ -z "${CLANG_FORMAT:-}" ]; then | ||
| if command -v clang-format-20 >/dev/null 2>&1; then | ||
| CLANG_FORMAT="clang-format-20" | ||
| else | ||
| echo "Error: clang-format-20 is required (other versions differ in style)" >&2 | ||
| exit 1 | ||
| fi | ||
| fi | ||
|
|
||
| # One scratch file removed on any exit, rather than one per iteration that a | ||
| # mid-loop failure would leave behind. | ||
| expected=$(mktemp) | ||
| trap 'rm -f "$expected"' EXIT | ||
|
|
||
| ret=0 | ||
| while IFS= read -r -d '' file; do | ||
| # Keep clang-format's own diagnostics: a parse or config error otherwise | ||
| # aborts the run with a bare exit code and nothing to act on. | ||
| if ! err=$("$CLANG_FORMAT" --style=file "$file" 2>&1 >"$expected"); then | ||
| echo "Error: clang-format failed on $file" >&2 | ||
| [ -n "$err" ] && printf '%s\n' "$err" >&2 | ||
| ret=1 | ||
| continue | ||
| fi | ||
| [ -n "$err" ] && printf '%s\n' "$err" >&2 | ||
| if ! diff -u -p --label="$file" --label="expected coding style" "$file" "$expected"; then | ||
| ret=1 | ||
| fi | ||
| done < <(git ls-files -z -- 'examples/*.c') | ||
|
|
||
| exit $ret |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #!/usr/bin/env bash | ||
| # Every tracked C example must end with a newline. | ||
| # | ||
| # minted reproduces the file as-is, so a missing final newline shows up in the | ||
| # typeset listing as well as annoying every diff that touches the last line. | ||
| set -e -u -o pipefail | ||
|
|
||
| ret=0 | ||
| while IFS= read -r -d '' f; do | ||
| if [ ! -s "$f" ]; then | ||
| # tail -c1 of an empty file is empty, which would otherwise read as a | ||
| # correctly terminated file. | ||
| echo "Warning: empty file $f" | ||
| ret=1 | ||
| elif file --mime-encoding "$f" | grep -qv binary; then | ||
| if [ -n "$(tail -c1 <"$f")" ]; then | ||
|
cubic-dev-ai[bot] marked this conversation as resolved.
|
||
| echo "Warning: No newline at end of file $f" | ||
| ret=1 | ||
| fi | ||
| fi | ||
| done < <(git ls-files -z -- 'examples/*.c') | ||
|
|
||
| exit $ret | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| #!/usr/bin/env bash | ||
| # Reject unsafe C idioms in the examples the book prints. | ||
| # | ||
| # Readers copy this code. The concurrency defects the manuscript keeps on | ||
| # purpose are discussed in the text; an unbounded string function smuggled in | ||
| # by a later edit would not be, so catch that class here. | ||
| set -u -o pipefail | ||
|
|
||
| failed=0 | ||
|
|
||
| banned='(^|[^[:alnum:]_])(gets|sprintf|vsprintf|strcpy|stpcpy|strcat|atoi|atol|atoll|atof|mktemp|tmpnam|tempnam)[[:space:]]*\(' | ||
| secrets='(password|secret|api_key|private_key|token)[[:space:]]*=[[:space:]]*"[^"]+' | ||
| # undef of either guard disables hardening whatever the value; only the define | ||
| # side needs to pin _FORTIFY_SOURCE to 0 to be worth reporting. | ||
| dangerous_pp='#[[:space:]]*(undef[[:space:]]+(_FORTIFY_SOURCE|__SSP__)|define[[:space:]]+(_FORTIFY_SOURCE[[:space:]]+0|__SSP__))' | ||
|
|
||
| # Blank out comments while keeping one output line per input line, so prose | ||
| # that names a banned function cannot fail the build and the line numbers | ||
| # reported below still refer to the real file. | ||
| # | ||
| # Two details are what make this safe rather than merely convenient. A comment | ||
| # becomes a space, as it does in translation phase 3, because deleting it would | ||
| # splice the tokens on either side and "_FORTIFY_SOURCE/**/0" would stop | ||
| # looking like a definition of it. And quoted literals are copied out | ||
| # untouched, honouring backslash escapes, because a string holding "/*" would | ||
| # otherwise put the scanner in a comment and swallow the code after it. | ||
| # Literals have to survive anyway: the secret pattern below matches on them. | ||
| strip_comments() { | ||
| awk ' | ||
| BEGIN { in_block = 0; buf = ""; held = 0 } | ||
| { | ||
| # Translation phase 2 first: a backslash-newline is deleted before | ||
| # anything is tokenized, whatever precedes it. Doing this ahead of the | ||
| # scan is what keeps a spliced string, a spliced // comment, and a | ||
| # backslash run at end of line from being read differently here than | ||
| # by the compiler. Blank lines stand in for the lines folded away, so | ||
| # reported line numbers keep pointing into the file. | ||
| buf = buf $0 | ||
| if (substr($0, length($0), 1) == "\\") { | ||
| sub(/\\$/, "", buf) | ||
| held++ | ||
| next | ||
| } | ||
| emit() | ||
| } | ||
| END { if (buf != "" || held > 0) emit() } | ||
|
|
||
| function emit( k) { | ||
| print scan(buf) | ||
| for (k = 0; k < held; k++) print "" | ||
| buf = ""; held = 0 | ||
| } | ||
|
|
||
| # in_block is deliberately global: a block comment spans logical lines. | ||
| # A literal cannot, once phase 2 has run, so quote state is local. | ||
| function scan(s, out, i, n, ch, nx, in_str, in_chr) { | ||
| out = ""; i = 1; n = length(s); in_str = 0; in_chr = 0 | ||
| while (i <= n) { | ||
| ch = substr(s, i, 1); nx = substr(s, i + 1, 1) | ||
| if (in_block) { | ||
| if (ch == "*" && nx == "/") { in_block = 0; i += 2 } else { i++ } | ||
| continue | ||
| } | ||
| if (in_str || in_chr) { | ||
| out = out ch | ||
| if (ch == "\\") { out = out nx; i += 2; continue } | ||
| if (in_str && ch == "\"") in_str = 0 | ||
| if (in_chr && ch == "'"'"'") in_chr = 0 | ||
| i++ | ||
| continue | ||
| } | ||
| if (ch == "\"") { in_str = 1; out = out ch; i++; continue } | ||
| if (ch == "'"'"'") { in_chr = 1; out = out ch; i++; continue } | ||
| if (ch == "/" && nx == "*") { in_block = 1; out = out " "; i += 2; continue } | ||
| if (ch == "/" && nx == "/") break | ||
| out = out ch; i++ | ||
| } | ||
| return out | ||
| }' "$1" | ||
| } | ||
|
|
||
| # Here-strings rather than "echo ... | grep -q": grep exits on first match, the | ||
| # writer takes SIGPIPE, and under pipefail the condition then reads as false, | ||
| # which would silently pass a file that does contain a banned call. | ||
| while IFS= read -r -d '' f; do | ||
| code=$(strip_comments "$f") | ||
|
|
||
| if grep -qE "$banned" <<<"$code"; then | ||
| echo "Banned function in $f:" | ||
| grep -nE "$banned" <<<"$code" | ||
| failed=1 | ||
| fi | ||
| if grep -iqE "$secrets" <<<"$code"; then | ||
| echo "Possible hardcoded secret in $f:" | ||
| grep -inE "$secrets" <<<"$code" | ||
| failed=1 | ||
| fi | ||
| if grep -qE "$dangerous_pp" <<<"$code"; then | ||
| echo "Dangerous preprocessor directive in $f:" | ||
| grep -nE "$dangerous_pp" <<<"$code" | ||
| failed=1 | ||
| fi | ||
| done < <(git ls-files -z -- 'examples/*.c') | ||
|
|
||
| if [ $failed -eq 0 ]; then | ||
| echo "Security checks passed." | ||
| fi | ||
|
|
||
| exit $failed |
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
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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.