Skip to content

Race condition in webui-node-modules between deps:log-viewer extraction and checksum validation #2167

@junhaoliao

Description

@junhaoliao

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:

  1. (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.
  2. (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/).
  3. After both deps finish: yscope-log-viewer/node_modules/ no longer exists, but the checksum file from (C) still indicates it's valid.
  4. 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.
  5. 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:

  1. Run a full build: task webui
  2. 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)
  3. Run task webui again
  4. 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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions