Repository navigation
An analysis can be given a time limit (4.2.41) - #800
Merged
ddehilster merged 2 commits intoOct 26, 2026
Merged
ddehilster merged 2 commits into
ddehilster merged 2 commits into
Conversation
NLP++ is a C++ extension. A grammar whose loop never ends cannot be stopped from outside -- a Python caller has no thread to interrupt, only a process to kill -- and a loop that makes a string a turn grows until the process is killed for its memory. One such loop took a document extractor down five times in half an hour on one document, and with it every analysis queued behind that document. - NLP_ENGINE::setRunLimit(ms) puts a limit on each text's analysis; 0, the default, is none. lastRunStopped() says whether the last analyze() or analyzeStream() call stopped a run at it. - Each Parse takes the limit when it is made. Parse::overBudget is asked on every while turn (reading the clock every 256th time) and before every pass. Past the limit, the loop fails its region, no more passes run, and the stop is reported once in err.log and on stderr, naming the pass and its file. The run's string table is freed with it as usual, so the memory comes back. - Compiled analyzers get the same check: the generator writes Arun::overbudget(nlppp) into every while condition. - nlp -TIMELIMIT <seconds>. A run it stops exits 2: neither success nor the missing analyzer or input that exits 1. Fixture run-limit loops forever in pass 3 and checks that pass 2 ran, the line after the loop and pass 4 did not, the message is on stderr, and nlp exits 2. On the analyzer that hung in production (with the old string functions, so it still loops) -TIMELIMIT 5 stops it at 5 seconds. No limit, no change: 881 fixture inputs of 17 production analyzers give byte-identical output.json to 4.2.39, and 3 million while turns take the same time with or without a limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
my_tchar.h maps each <tchar.h> name nlp uses to its char function on platforms without one; _tstof was not among them, so main.cpp did not compile there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 26, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
NLP++ runs as a C++ extension, so a grammar whose loop never ends can't be stopped from outside. A Python caller has no thread to interrupt, only a process to kill. And a loop that makes a new string every turn keeps growing until the process is killed for its memory. One such loop took a document extractor down five times in half an hour on one document, along with every analysis queued behind it. The loop itself came from the string-position bug fixed in #799; this PR covers the next loop, whatever causes it.
API
NLP_ENGINE::setRunLimit(ms): a limit on each text's analysis.0(the default) means no limit.NLP_ENGINE::lastRunStopped(): true after ananalyze()/analyzeStream()call that stopped a run at the limit.nlp -TIMELIMIT <seconds>: a run it stops exits 2. That's distinct from success (0) and from the missing analyzer or input that exits 1.How it stops
Parsetakes the limit when it's created.Parse::overBudget()is checked on everywhileturn (it reads the clock every 256th time) and before every pass.err.logand on stderr, naming the pass and its file:[Run stopped: past its time limit of 2000 ms in pass 3 (loop); the rest of the analysis was not run.]Arun::overbudget(nlppp)into everywhilecondition.Tests
run-limit, run on Windows, Linux and macOS. It loops forever in pass 3, and checks that pass 2 ran, that neither the line after the loop nor pass 4 ran, that the message is on stderr, and that the exit status is 2.-TIMELIMIT 5stops it at 5 s with exit 2.No limit means no change
output.jsonto 4.2.39.whileturns take the same time (about 3.0–3.2 s) with no limit and with a 600 s limit.compiled-bridge, and the analyzers checkout fortest-nlp.This is rebased on #799 and builds as 4.2.41. The
str-positionsandrun-limitsteps both pass on the combined build.The NLPPlus side (
analyze(..., timeout=)) follows once this is in a release.🤖 Generated with Claude Code