[Bug]: Closing a parallel result iterator early hangs while joining workers
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 3.2k
- Forks
- 248
- Avg merge
- 4d 8h
- Merged PRs (30d)
- 4
Description
What happened?
Parallel embedding uses ParallelWorkerPool.ordered_map(), which returns a generator backed by worker processes. If a caller consumes only a prefix of the results and then closes the iterator, close() never returns and a worker process is left blocked.
The same cleanup path is reached if iteration is interrupted by an exception. semi_ordered_map() sends stop signals only after the input stream is exhausted, but its finally block always calls join(). On early generator exit, workers are still waiting on the input queue, so the parent waits indefinitely.
What is the expected behaviour?
Closing or abandoning a partially consumed parallel result iterator should promptly stop its workers and release the multiprocessing queues. Fully consumed iterators should keep the normal graceful join path.
A minimal reproducible example
from fastembed.parallel_processor import ParallelWorkerPool, Worker
class EchoWorker(Worker):
@classmethod
def start(cls, **kwargs):
return cls()
def process(self, items):
yield from items
pool = ParallelWorkerPool(1, EchoWorker, start_method="fork")
results = pool.ordered_map(range(1000))
assert next(results) == 0
results.close() # hangs indefinitely on ParallelWorkerPool.join()
What Python version are you on? e.g. python --version
Python 3.11.15, installed with uv
FastEmbed version
Current main at 685fd9b (0.8.0)
What os are you seeing the problem on?
MacOS
Relevant stack traces and/or logs
There is no exception. The main process blocks in ParallelWorkerPool.join() while the worker remains blocked in input_queue.get().
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in fastembed.parallel_processor at ParallelWorkerPool.ordered_map(), semi_ordered_map(), and join(), then run the provided EchoWorker reproducer on Python 3.11. Verify that closing or abandoning a partially consumed iterator stops workers and releases queues promptly, while fully consumed iterators still use the graceful join path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- distributed-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100