fix: ensure executor doesn't deadlock when closure errors #152
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.
When running 'gomod2nix' on in my project, the 'gomod2nix import' was failing for every import. I have more imports than the default maxJobs.
This caused a deadlock and the program never finished, due to an issue in the ParallelExecutor.
This is because in the erroring case, we send to the errChan, which is a blocking channel. If this blocks then the defers are never called, most importantly the
defer
which pulls an entry off the semaphore (e.guard).This means once the erroring work functions exceeds the numWorkers, we will block trying to acquire the semaphore when we call .Add with more work.
We never get to the point where we call .Wait(), which would drain the errChan becuase we are blocked on the semaphore whilst we are still generating work.
This change moves the semaphore acquire to within the goroutines themselves. This alters the behaviour in that we now will start as many goroutines as we have work items, but the work they do will still be gated by the semaphore.
This is reasonable behaviour: goroutines are cheap, in general this package is useful if the work the functions are doing is expensive not the goroutine creation itself. The work still is guarded by the semaphore.
There is also a regression test added and in passing, the spelling of Parallel is corrected.