Skip to content

Fix empty kp hang#2799

Open
schanzer wants to merge 4 commits into
masterfrom
fix-empty-kp-hang
Open

Fix empty kp hang#2799
schanzer wants to merge 4 commits into
masterfrom
fix-empty-kp-hang

Conversation

@schanzer

@schanzer schanzer commented Jun 15, 2026

Copy link
Copy Markdown
Member

The actual symptom of the stale cache bug:

  • at times, massage-course could leave an empty cache file
  • since the file exists, the lua sread calls in Phase 2 try to parse it
  • but it's empty, with no EOF tag -- so lua runs forever

The three commits in this PR adds a nil check to the sread calls, make sure that merge-pathway-tocs can throw an error and keep going rather than choking, and makes massage-course atomic so that it never generates an empty file

schanzer and others added 3 commits June 15, 2026 10:38
The s-expression reader's inner loops (sread_line, sread_block_comment,
sread_atom, sread_string) only broke on specific characters and never
checked for nil, which io.read(1) returns at EOF. On an empty or truncated
input the reader looped forever at 100% CPU. sread() also dispatched a nil
peek into sread_atom, so even a 0-byte file would spin.

This was the root of the intermittent `make` hang on "Make pathway-tocs.js":
a 0-byte .workbook-lessons.rkt.kp fed sread_file, which never returned.

Treat nil (EOF) as terminating in every loop, and have sread() return
false when the input is exhausted. Verified: a 0-byte file now returns
false immediately, a valid list still parses identically, and a truncated
(unterminated) list returns without hanging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The loop guarded only on file_exists_p, then fed the file to sread_file and
iterated the result with ipairs. A 0-byte .workbook-lessons.rkt.kp slipped
past the existence check; with the sread EOF fix it now returns false, which
ipairs() can't iterate.

Guard on the parsed result: if sread_file doesn't return a table, warn and
skip the course. Verified by emptying __sample's .kp and running the script
-- it now skips __sample with a warning and emits a well-formed pathway-tocs.js
for the remaining courses, instead of hanging or crashing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
make-workbook-lessons-list.lua opens its output with 'w', truncating the
target to 0 bytes the instant it starts; a crash/interrupt then leaves a
0-byte file behind, which a later incremental build's reader consumed (the
source of the pathway-tocs hang). The no-lesson-order branch also created a
deliberately empty file via `touch`.

Publish atomically: write to a .tmp and mv it into place only on success,
so an interrupted run leaves the previous good file intact rather than an
empty one. For the no-lesson-order case, write a valid empty list "()"
instead of a 0-byte touch.

Verified: bash -n passes, "()" parses as an empty list, and a simulated
mid-populate failure leaves the prior file contents untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@schanzer schanzer requested a review from ds26gte June 15, 2026 15:45
@ds26gte

ds26gte commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

As mentioned in private slack, an alternate fix -- a simple rewrite of make-workbook-lessons-list.lua -- in branch fix-empty-kp-hang-within-lua appears to be enough.

@schanzer

Copy link
Copy Markdown
Member Author

@ds26gte I appreciate the poke! I'm testing your fix locally today on my local machine, and if the problem doesn't re-appear I'll merge

@schanzer

Copy link
Copy Markdown
Member Author

@ds26gte Confirming that this fixes one issue, but not all of them.

Your fix eliminates one of the sources of a 0-byte files (pathways with no lesson-order.txt files), but not all of them (a halted make). As you pointed out, this branch is complimentary in that it addresses the infinite loop by modifying sread_file to watch out for 0-byte files in the first place. But it also fixes the crash by adding a guard to make-pathway-tocs and makes massage-course atomic by using the temp file.

I've cherry-picked your change into this branch, and will merge it to master after some testing.

@schanzer schanzer changed the base branch from master to ai June 18, 2026 00:47
@schanzer schanzer changed the base branch from ai to master June 18, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants