Improved userspace tunnel concurrency to avoid race conditions. #503
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.
The problem is described in the issue #502. A potential solution to this problem is to close the reader and writer after the io,Copy() and sending result (EOF, error) to the error channel. By closing the writer and reader the counter part io.Copy() will drain and unblocked. By this change the code will be resistant to one side network connection closes.
The close function needs to be synced with sync.Once to avoid multiple entrance so double freeing.
Apart from this it is essential to use buffered channel like
errCh := make(chan error, 2)
Because, buffered channel sender and receiver should be synced at the same time. This means if the code doesn't reach
at the same time with the line in ioCopyWithErr
errCh <- err
Then it will be dead/circular locked.
I've tested it with different scenarios as mentioned in #502 and it worked very performant and with no locking issue at all.
I'm not a golang expert but after some extensive research this solution seems robust.