Comments (5)
@martinandersson Below is my explanation of the problem and the fix.
The method AsynchronousTlsChannelGroup.RegisteredSocket.close
may be called by any thread as a result of it calling
AsynchronousTlsChannel.close
. AsynchronousTlsChannelGroup.RegisteredSocket.close
calls SelectionKey.cancel
, which
Requests that the registration of this key's channel with its selector be cancelled. Upon return the key will be invalid and will have been added to its selector's cancelled-key set. The key will be removed from all of the selector's key sets during the next selection operation.
If we now look at Selector
, we can see that
The cancelled-key set is the set of keys that have been cancelled but whose channels have not yet been deregistered. This set is not directly accessible. The cancelled-key set is always a subset of the key set.
This means that selector.keys
in AsynchronousTlsChannelGroup.processPendingInterests
may return cancelled SelectionKey
s. Calling key.interestOps
on such SelectionKey
s results in CancelledKeyException
as per the documentation of SelectionKey.interestOps
.
Thus, depending on how AsynchronousTlsChannelGroup
and AsynchronousTlsChannel
are used in a program, the program may have a race condition.
Two approaches are possible:
- change the usage of
SelectionKey.cancel
,Selector.select
,Selector.keys
,SelectionKey.isValid
,SelectionKey.interestOps
methods
inAsynchronousTlsChannelGroup
in such a way that there can be no such race condition anymore; - catch and ignore
CancelledKeyException
when it happens as a result of a program having the race condition.
The second approach seems (maybe surprisingly) more optimal in this case because it is both simpler and introduces smaller performance overhead assuming that CancelledKeyException
is thrown much more rarely than the method SelectionKey.cancel
is called.
from tls-channel.
Hi Jeff, thanks for the report. I tried a bit but could not reproduce the problem. However, what you suggests makes sense and is completely consistent with the other catch we already have, so I just added it. It's in master already.
Best regards.
from tls-channel.
Why is this exception ignored? There's probably an assumption involved there. Can this be officially explained in docs somewhere?
from tls-channel.
Oh, I can only agree. Exceptions are most definitely a valid branching mechanism. I use it myself from time to time. If you ask me, I think any performance degradation - if t here is any - is probably negligible and should not really matter other than how we design our API. For example I would give my users a method boolean hasNext()
in order to keep their code "clean", but if a particular interface is only used internally then I might just as well skip adding the method and only rely on the client catching a NoSuchElementException
. But I am sure I am preaching to the choir here hahaha, love your reply! Detailed. So thank you! The only thing I'd like to add is that your answer should perhaps be copy-pasted into internal documentation?
from tls-channel.
The Selector API is already racy here. But a lot of "closing workflows" are racy and benign, as typically not much happens after a close to matter anyway.
Something that would help: having a test that show non-deterministic behavior due to this race.
from tls-channel.
Related Issues (20)
- Spin Loop when underlying channel is closed HOT 7
- NonBlockingClient example HOT 2
- Handshake don't work HOT 1
- An example for how to use this with AsyncHttpClient HOT 1
- TLS Termination HOT 2
- When using SniSslContextStrategy non tls connections will hang indefinitely HOT 3
- Selector is not triggering HOT 1
- ClientTLSChannel#read sometimes hangs HOT 7
- License clarification needed HOT 1
- client channel reads only first TLS record HOT 1
- Call to Class.getMethod causing issue on GraalVM HOT 2
- ByteChannel immediately returning -1? HOT 5
- Closing an `AsynchronousTlsChannel` concurrently with an `AsynchronousTlsChannelGroup` registering it sometimes causes termination of the `selectorThread` HOT 7
- ClientTlsChannel.Builder.withEngineFactory? HOT 3
- How to Contribute HOT 2
- Dependency Dashboard
- Action Required: Fix Renovate Configuration
- Unable to run SimpleBlockingClient and Server HOT 1
- multi-threading example HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tls-channel.