Bug
A race condition exists in the webui-node-modules task (taskfile.yaml:354) caused by its concurrently-running deps deps:log-viewer and utils:checksum:validate for yscope-log-viewer/node_modules. Both deps operate on overlapping paths under components/webui/yscope-log-viewer/, and since Task runs deps concurrently by default, their operations can interleave in ways that produce incorrect build state.
webui-node-modules has four concurrent deps:
deps:
- "deps:log-viewer" # (A)
- "nodejs-22" # (B)
- task: "utils:checksum:validate" # (C)
vars:
CHECKSUM_FILE: "{{.G_WEBUI_LOG_VIEWER_NODE_MODULES_CHECKSUM_FILE}}"
INCLUDE_PATTERNS: ["{{.LOG_VIEWER_OUTPUT_DIR}}"]
- task: "utils:checksum:validate" # (D)
vars:
CHECKSUM_FILE: "{{.G_WEBUI_PACKAGE_NODE_MODULES_CHECKSUM_FILE}}"
INCLUDE_PATTERNS: ["{{.PACKAGE_OUTPUT_DIR}}"]
Dep (A) calls yscope-dev-utils:remote:download-and-extract-tar (tools/yscope-dev-utils/exports/taskfiles/utils/remote.yaml:66), which when the stored checksum is stale, runs:
rm -rf "components/webui/yscope-log-viewer" # deletes EVERYTHING including node_modules/
mkdir -p "components/webui/yscope-log-viewer"
tar --extract ... --directory "components/webui/yscope-log-viewer" ...
Dep (C) calls utils:checksum:validate (tools/yscope-dev-utils/exports/taskfiles/utils/checksum.yaml:82), which computes a checksum of yscope-log-viewer/node_modules/ by running tar --create piped into md5sum.
Because (A) and (C) run concurrently with no ordering between them:
- (C) starts:
checksum:compute reads the existing yscope-log-viewer/node_modules/ (from a previous build) and computes a checksum that matches the stored checksum file, so checksum:validate keeps the checksum file intact.
- (A) starts:
download-and-extract-tar decides it needs to re-extract. It runs rm -rf yscope-log-viewer/, then extracts the tar (which doesn't include node_modules/).
- After both deps finish:
yscope-log-viewer/node_modules/ no longer exists, but the checksum file from (C) still indicates it's valid.
webui-node-modules may be considered up-to-date (both generates files exist and sources haven't changed), so it skips cmds, leaving yscope-log-viewer/node_modules/ missing.
- Downstream tasks fail because the
webui build expects yscope-log-viewer/node_modules/ to exist.
Alternatively, if (A) starts deleting yscope-log-viewer/ while (C) is mid-way through tar --create | md5sum, the tar process encounters files that vanish mid-read. Since IGNORE_ERROR is set to "true" inside checksum:validate, the error is swallowed and the resulting checksum file is unreliable.
This is analogous to the race condition described in #1477 where concurrent tasks accessed shared cmake settings files.
CLP version
22c1275
Environment
All platforms (Linux, macOS). The issue depends on task scheduling timing, so it may manifest intermittently.
Reproduction steps
The issue is timing-dependent and more likely to trigger on a clean or stale build where deps:log-viewer decides to re-extract:
- Run a full build:
task webui
- Make a change that causes
deps:log-viewer to re-extract (e.g., change the FILE_SHA256 or URL in taskfiles/deps/main.yaml, or delete build/deps/log-viewer.md5)
- Run
task webui again
- Observe that the build intermittently fails because
yscope-log-viewer/node_modules/ is missing or incomplete
The race is easiest to reproduce by adding an artificial delay in download-and-extract-tar between rm -rf and tar --extract, which widens the window for checksum:validate to observe the deleted state.
Bug
A race condition exists in the
webui-node-modulestask (taskfile.yaml:354) caused by its concurrently-running depsdeps:log-viewerandutils:checksum:validateforyscope-log-viewer/node_modules. Both deps operate on overlapping paths undercomponents/webui/yscope-log-viewer/, and since Task runs deps concurrently by default, their operations can interleave in ways that produce incorrect build state.webui-node-moduleshas four concurrent deps:Dep (A) calls
yscope-dev-utils:remote:download-and-extract-tar(tools/yscope-dev-utils/exports/taskfiles/utils/remote.yaml:66), which when the stored checksum is stale, runs:Dep (C) calls
utils:checksum:validate(tools/yscope-dev-utils/exports/taskfiles/utils/checksum.yaml:82), which computes a checksum ofyscope-log-viewer/node_modules/by runningtar --createpiped intomd5sum.Because (A) and (C) run concurrently with no ordering between them:
checksum:computereads the existingyscope-log-viewer/node_modules/(from a previous build) and computes a checksum that matches the stored checksum file, sochecksum:validatekeeps the checksum file intact.download-and-extract-tardecides it needs to re-extract. It runsrm -rf yscope-log-viewer/, then extracts the tar (which doesn't includenode_modules/).yscope-log-viewer/node_modules/no longer exists, but the checksum file from (C) still indicates it's valid.webui-node-modulesmay be considered up-to-date (bothgeneratesfiles exist andsourceshaven't changed), so it skipscmds, leavingyscope-log-viewer/node_modules/missing.webuibuild expectsyscope-log-viewer/node_modules/to exist.Alternatively, if (A) starts deleting
yscope-log-viewer/while (C) is mid-way throughtar --create | md5sum, thetarprocess encounters files that vanish mid-read. SinceIGNORE_ERRORis set to"true"insidechecksum:validate, the error is swallowed and the resulting checksum file is unreliable.This is analogous to the race condition described in #1477 where concurrent tasks accessed shared cmake settings files.
CLP version
22c1275
Environment
All platforms (Linux, macOS). The issue depends on task scheduling timing, so it may manifest intermittently.
Reproduction steps
The issue is timing-dependent and more likely to trigger on a clean or stale build where
deps:log-viewerdecides to re-extract:task webuideps:log-viewerto re-extract (e.g., change theFILE_SHA256orURLintaskfiles/deps/main.yaml, or deletebuild/deps/log-viewer.md5)task webuiagainyscope-log-viewer/node_modules/is missing or incompleteThe race is easiest to reproduce by adding an artificial delay in
download-and-extract-tarbetweenrm -rfandtar --extract, which widens the window forchecksum:validateto observe the deleted state.