fix(desktop): bound Slack Redux node decoder with context - #163
Conversation
Slack Desktop IndexedDB decode spawned node with exec.Command and cmd.Output and never honored cancel. A hung decoder parked sync and watch, and Ctrl-C could not kill the child. Pass the ingest context through Extract, spawn with CommandContext, and stop the blob loop when the context is done. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 30, 2026, 3:15 PM ET / 19:15 UTC. ClawSweeper reviewWhat this changesThe PR passes command context through Slack Desktop IndexedDB extraction so a hung Node-based Redux decoder is terminated when the caller cancels. Regression provenancePossible regression — probable (reviewed change; failure trace). No predecessor PR is attributed. Merge readinessKeep this PR open for maintainer merge review: it is a focused, source-aligned repair for a desktop-command cancellation hang, with sufficient production-path terminal proof and no actionable correctness finding. Priority: P2 Review scores
Verification
How this fits togetherSlack Desktop import snapshots local IndexedDB data and invokes Node to decode supported Redux blobs. The extracted workspace data feeds sync, watch, and doctor command flows. flowchart LR
A[CLI sync watch doctor] --> B[Desktop import]
B --> C[IndexedDB snapshot]
C --> D[Redux blob decoder]
D --> E[Node process]
E --> F[Workspace data]
A --> G[Cancellation context]
G --> D
G --> E
Before merge
Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Merge the focused context propagation and cancellation test so a hung local Node decoder cannot keep a desktop command running after cancellation. Do we have a high-confidence way to reproduce the issue? Yes. The prior source launched Node without a context on the documented desktop extraction path, and the supplied after-fix terminal trace exercises patched public Is this the best way to solve the issue? Yes. Passing the existing command context to the sole Node spawn and stopping the blob loop on cancellation is the narrowest maintainable repair while retaining normal decoding and per-blob error handling. AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against dcbc12d44837. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (3 earlier review cycles) |
|
Maintainer triage: recommend LAND. No source repair was needed. The docs/changelog follow-up is on I reproduced the hang through the real built CLI using a synthetic IndexedDB blob and a temporary GOWORK=off go build -o /tmp/slacrawl-main ./cmd/slacrawl # main
GOWORK=off go build -o /tmp/slacrawl-163 ./cmd/slacrawl # PR head
python3 proof-cancel.py desktop /tmp/slacrawl-main /tmp/slacrawl-163Commands exercised: Codex autoreview returned scoped-clean on both the production patch and the docs follow-up (the skill's default P0 scope). Existing GitHub CI is green. The test injects the hung child locally; it does not claim a naturally hung production Slack profile. |
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Preserve all Unreleased fixes and maintenance notes after landing openclaw#159. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
steipete
left a comment
There was a problem hiding this comment.
Reviewed the integrated desktop cancellation patch and docs/changelog follow-up. The desktop tests passed locally, and the earlier synthetic built-CLI proof confirms SIGINT stops sync, watch, and doctor and cleans up the hung child. Codex autoreview found no actionable findings in its default P0 scope. Thanks @SebTardif.
|
Landed as c00d998 with the docs/changelog follow-up. Thanks @SebTardif! Final head 9d2751c passed |
Preserve all Unreleased fixes and maintenance notes after landing openclaw#159 and openclaw#163. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
What Problem This Solves
Fixes an issue where users running
slacrawl sync --source desktoporslacrawl watchwould hang forever when Slack Desktop IndexedDB decode spawned Node and that child never returned. Ctrl-C canceled the Go context, but the Node process kept running, so the CLI stayed parked.Why This Change Was Made
The ingest context now reaches Extract and the Redux decoder. Node is started with CommandContext, and the blob loop stops when that context is done. Decode framing is unchanged. This does not restack the HTTP client timeout (#126) or the repeated-cursor guard (#159).
User Impact
A stuck Slack Desktop decode no longer holds the CLI after cancel. Sync, watch, and doctor can return when the user stops the command.
Evidence
Call chain:
slacrawl sync --source desktop/watch->slackdesktop.Ingest->Extract->extractIndexedDBStates->runReduxDecoder. The decoder usedexec.Command("node", ...)andcmd.Output()with no deadline. That spawn has been unbounded since desktop IndexedDB decode landed (2026-03-08, later kept in 0678e7f on 2026-04-27).Before the patch, cancel did not stop a decoder that only called
setTimeout:After the patch, public
Extractwith a hanging Node on PATH returns when the 400ms context deadline fires:The same CommandContext contract kills a hung Node child:
Real behavior proof
Behavior or issue addressed: Slack Desktop Redux decode spawned Node with no context, so a hung child parked sync/watch and survived Ctrl-C.
Real environment tested: macOS, Go 1.26, Node on PATH. Patched slacrawl at
/tmp/oc-pr-slacrawl-F003. Fixture: recognized V8 IndexedDB blob plus a hanging Node wrapper that only calls setTimeout.Exact steps or command run after this patch: Built
/tmp/f003prooffrom the patched module and ranExtractagainst that blob withPATHpointing at the hanging Node wrapper and a 400ms context deadline. Also ran CommandContext againstnode -e "setTimeout(function () {}, 1e9)".Evidence after fix: terminal output from the patched Extract binary and from CommandContext:
Observed result after fix: Extract returned
context deadline exceededin 402ms instead of waiting on Node. The hung Node child was killed (signal: killed) when the context fired.What was not tested: A real Slack Desktop profile whose IndexedDB blob hangs inside the stock decoder script, and a live Ctrl-C against that profile.