Deadlock fixed - result channel buffer increased

Although the result channel send operation and context cancel are
guarded by the same mutex and context is cancelled by the main thread
when it receives a result message from the channnel, there is absolutely
no guarantee that one goroutine can't write result to the channel after
the first goroutine did the same and before the main thread cancelled
the context. This is the following scenario:

- Worker #1 acquires mutex, writes to the result channel
- Worker #2 acquires mutex, writes to the result channel
- Main thread reads from the result channel, acquires mutex, cancels the
context

Since our result channel (and error channel) had buffer of size 1, the
Worker #2 was hanging indefinitely. Setting the buffer size to the
number of goroutines fixed the problem.

Alternative scenario was:

- Worker #1 acquires mutex, writes to the result channel
- Main thread acquires mutex, reads from the result channel, cancels the
context
- Worker #2 receives cancel notification so it completes without
yielding the result

That's why deadlock was happening only from time to time.
This commit is contained in:
Piotr Dyraga committed 2018-07-30 09:56:40 +02:00
1 parent 65d7ad4e73
commit 530e40c1d4
1 file changed
+3 -3
+3 -3
View File
@@ -68,19 +68,19 @@ func GenerateSafePrime(
return nil, nil, errors.New("safe prime size must be at least 6 bits")
}
primeChan := make(chan safePrime, 1)
errChan := make(chan error, 1)
primeChan := make(chan safePrime, concurrencyLevel)
errChan := make(chan error, concurrencyLevel)
defer close(primeChan)
defer close(errChan)
mutex := &sync.Mutex{}
waitGroup := &sync.WaitGroup{}
waitGroup.Add(concurrencyLevel)
ctx, cancel := context.WithCancel(context.Background())
for i := 0; i < concurrencyLevel; i++ {
waitGroup.Add(1)
runGenPrimeRoutine(
ctx, primeChan, errChan, mutex, waitGroup, random, bitLen,
)