SMBClient stores the established connections in connectionTable for caching. Before returning a cached connection, it checks if the connection is still alive calling Connection.isConnected(). This method relies on the underlying Socket but in Java the Socket may not be aware that the other end has been disconnected (e.g. server restart). Socket.isConnected() / .isClosed() are related to the Socket lifecycle controlled from the code which not necessary reflects the network events. Even if these methods return "connected", the current state can be "broken pipe" which is only revealed when the client tries to write something on the wire.
So SMBClient can return a stale/dead connection from the cache. It is not an issue when a simple SMB share is used because the first thing is to open a Session on the connection and it will fail immediately. In this case the Connection can be closed and reopened from the application code.
However, in case of DFS the smbj library opens and maintains connections under the hood and the application only knows the connection to the namespace server. This "main" connection can be fine while other connections to the data servers are already dead.
I think it would make sense to extend the connection check with some "wire test" and SMB Echo message seems good to me for this purpose.
What do you think about using something like this?
The application side workaround would be to close the whole SMBClient (with all connections in the cache) if failure happens because it is not possible to determine and access the problematic background connection from the application code. It is overkill because all connections would be closed and potentially live sessions would be aborted.
SMBClient
stores the established connections inconnectionTable
for caching. Before returning a cached connection, it checks if the connection is still alive callingConnection.isConnected()
. This method relies on the underlyingSocket
but in Java theSocket
may not be aware that the other end has been disconnected (e.g. server restart).Socket.isConnected()
/.isClosed()
are related to theSocket
lifecycle controlled from the code which not necessary reflects the network events. Even if these methods return "connected", the current state can be "broken pipe" which is only revealed when the client tries to write something on the wire.So
SMBClient
can return a stale/dead connection from the cache. It is not an issue when a simple SMB share is used because the first thing is to open aSession
on the connection and it will fail immediately. In this case theConnection
can be closed and reopened from the application code. However, in case of DFS thesmbj
library opens and maintains connections under the hood and the application only knows the connection to the namespace server. This "main" connection can be fine while other connections to the data servers are already dead.I think it would make sense to extend the connection check with some "wire test" and SMB Echo message seems good to me for this purpose.
What do you think about using something like this?
The application side workaround would be to close the whole
SMBClient
(with all connections in the cache) if failure happens because it is not possible to determine and access the problematic background connection from the application code. It is overkill because all connections would be closed and potentially live sessions would be aborted.