There's the following code in pool.py, line 494 and following:
debug('joining task handler')
task_handler.join()
debug('joining result handler')
task_handler.join()
It seems the last line should read `result_handler.join()` instead.
Additionally, when _terminate() is called, it seems the worker_handler could still run while other threads shut down existing workers, meaning it could start new workers (in _repopulate_pool()) in parallel.
So perhaps the worker_handler should be joined before anything else in _terminate(). It would incur a small latency, though (because of the sleep() call there).