Skip to content

Fix thread leak in threaded_generator when consumers exit early#721

Open
discobot wants to merge 1 commit into
allenai:mainfrom
discobot:fix/703-threaded-generator-leak
Open

Fix thread leak in threaded_generator when consumers exit early#721
discobot wants to merge 1 commit into
allenai:mainfrom
discobot:fix/703-threaded-generator-leak

Conversation

@discobot

Copy link
Copy Markdown

Fixes #703.

The issue correctly pinpoints threaded_generator. The mechanism: its fill_queue daemon thread feeds a bounded queue (maxsize=16 by default) with a plain blocking q.put and has no stop signal, so if the consumer drops the wrapper generator before exhausting it, the thread blocks on put forever once the queue fills.

What makes this grow steadily during training: the data loaders (data_loader.py and composable/data_loader.py) create num_threads of these wrappers per batch-iteration and abandon them whenever an epoch iterator isn't fully consumed — stopping mid-epoch, hitting max duration, recreating the iterator — stranding another batch of threads each time.

This adds a stop event: the producer puts with a short timeout and re-checks the event, and the consumer sets it and drains the queue from a finally block, which also runs on GeneratorExit when the wrapper is closed or garbage collected. Producer threads now exit promptly once their consumer goes away. Ordering, sentinel termination, and exception forwarding via OLMoThreadError are unchanged.

Testing: new regression test in src/test/utils_test.py — abandoning wrappers mid-iteration leaks all 8 fill_queue threads on main and none with this change — plus coverage for in-order full consumption and exception forwarding. src/test/data/data_loader_test.py and src/test/data/composable/data_loader_test.py pass.

The fill_queue thread blocks forever on q.put once its bounded queue
fills up if the consuming generator is abandoned before exhaustion,
which happens every time a data loader epoch iterator isn't fully
consumed. This leaks one thread per abandoned generator and CPU thread
count grows steadily over a training run. The producer now checks a
stop event while putting, and the consumer sets it and drains the queue
on exit, so the thread shuts down as soon as the consumer goes away.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@discobot discobot mentioned this pull request Jun 11, 2026
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.

CPU thread leaking

1 participant