JDK-8144144 : ORB destroy() leaks filedescriptors after unsuccessful connection
  • Type: Bug
  • Component: other-libs
  • Sub-Component: corba
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-11-26
  • Updated: 2016-07-21
  • Resolved: 2016-02-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 JDK 9
7u111Fixed 8u102Fixed 9 b107Fixed
Related Reports
Duplicate :  
Duplicate :  
Description

Customer application opens and closes corba connections to different servers.
These servers may be offline for an undefined time. In this situation the
application tries to reconnect periodically.

The problem is that ORB.destroy() obviously does not dispose fds. Not even
when forcing System.gc() / System.runFinalization()

The provided test program opens a corba connection to a non existent server
and closes it immediately over and over in a loop. Watch e.g.
with pfiles the unlimited growth of fds


Comments
a curious observation on windows 7: for each SocketOrChannelAcceptorImpl listening on port N, there appears to be a localhost connection from N+1 to N+2 i.e. 127.0.0.1.<N+1> to 127.0.0.1.<N+2>. These don't appear to be created by the ORB, as the socketfactory create calls are not observed in the call flows. In any case, adding the acceptor to the CorbaInboundConnectionCache and then closing it within the cache close call flow eliminates the perceived socket leak. Still need to clear the deferredRegistrations from within Selector close.
20-12-2015

That's correct. That might look like an option i.e. adding the Acceptor to the cache, BUT it is not a CorbaConnection, it's a listening end point. What could be done is the CorbaInboundConnectionCache adds a member which is its associated SocketOrChannelAcceptorImpl passed into its constructor and when the cache is closed the SocketOrChannelAcceptorImpl is closed also close the associated Acceptor. The close of the acceptor will close both the server socket channel and the server socket. The Connection caches both inbound and outbound are closed by the CorbaTransportManager. This closes the connection caches and the selector I think adding an Acceptor member to the CorbaInboundConnectionCache and have the close of the Acceptor managed via a close on the cache from the CorbaTransportManager is a good approach
19-12-2015

Thanks for analysis Mark. I spent some time on this myself yesterday. Serversockets being created in the SocketOrChannelAcceptorImpl.initialize() call are not being added to the connectionCache which is controlled and cleaned up by CorbaConnectionCacheBase class. i.e. public boolean initialize() { .... serverSocket = orb.getORBData().getSocketFactory() .createServerSocket(type, inetSocketAddress); CorbaConnection connection = new SocketOrChannelConnectionImpl(orb, this, serverSocket); .... } One proposal might be to add such sockets to the socket cache at this point in time. Something like : getConnectionCache().stampTime(connection); getConnectionCache().put(this, connection); You're right in that investigation would have to be done on whether this was a conscious design decision or not.
19-12-2015

the initial SocketOrChannelAcceptor created as a result of a POA instantiation is not being cleared and its ServerSocket/ServerSocketChannel closed and released as a result of the ORB.destroy call flow. The com.sun.corba.se.impl.transport.SelectorImpl.closed needs to be amended to handle this and to handle the clearing of any deferred registrations that might exist. The release of the underlying OS TCP socket requires that the encapsulated ServerSocket, which is created initially when the SocketOrChannelAcceptor was initialised, is explicitly closed. will test proposed fix with a CORBA test suite run i've analysed this issue on a JDK9 build. also check out whether the current behaviour is by design.
18-12-2015

I'm thinking that the CorbaTransportManager should be responsible for closing the connections that it's creating. Such a close() call is made in the ORBImpl.destroy() method. there is a condition on it however. I need to chase up to see that it's being invoked. I also need to confirm if these are the problem 'open' sockets that the submitter is referring to. ORBImpl... public void destroy() { ... synchronized (this) { if (status < STATUS_DESTROYED) { getCorbaTransportManager().close(); getPIHandler().destroyInterceptors(); status = STATUS_DESTROYED; } ... }
16-12-2015