JDK-8138819 : (se) File descriptor leak when Selector.open fails
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 8u60
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64
  • Submitted: 2015-08-21
  • Updated: 2016-06-13
  • Resolved: 2015-10-06
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 8 JDK 9
8u72Fixed 9 b85Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
 3.19.0-25-generic #26~14.04.1-Ubuntu SMP

EXTRA RELEVANT SYSTEM CONFIGURATION :
ulimit -n
1024


A DESCRIPTION OF THE PROBLEM :
EPollSelectorImpl doesn't  close 2 file descriptors (fd0, fd1) if pollWrapper throws exception:

    EPollSelectorImpl(SelectorProvider sp) throws IOException {
        super(sp);
        long pipeFds = IOUtil.makePipe(false);
        fd0 = (int) (pipeFds >>> 32);
        fd1 = (int) pipeFds;
        pollWrapper = new EPollArrayWrapper();
        pollWrapper.initInterrupt(fd0, fd1);
        fdToKey = new HashMap<>();
    }


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
 - Open many file descriptors: MAX_OPEN_FILE-2
 - Try create epoll selector
 - EPollSelectorImpl opens pipe and consume last 2 descriptors
 - EPollSelectorImpl calls epoll_create syscall 
 - EPollSelectorImpl throws IOException without closing pipe


REPRODUCIBILITY :
This bug can be reproduced rarely.


Comments
The same issue appears to be in linux/classes/sun/nio/ch/EPollSelectorImpl.java: long pipeFds = IOUtil.makePipe(false); unix/classes/sun/nio/ch/PollSelectorImpl.java: long pipeFds = IOUtil.makePipe(false); macosx/classes/sun/nio/ch/KQueueSelectorImpl.java: long fds = IOUtil.makePipe(false); solaris/classes/sun/nio/ch/DevPollSelectorImpl.java: long pipeFds = IOUtil.makePipe(false);
02-10-2015

- pollWrapper = new EPollArrayWrapper(); - pollWrapper.initInterrupt(fd0, fd1); - fdToKey = new HashMap<>(); + try { + pollWrapper = new EPollArrayWrapper(); + pollWrapper.initInterrupt(fd0, fd1); + fdToKey = new HashMap<>(); + } catch (Throwable t) { + FileDispatcherImpl.closeIntFD(fd0); + FileDispatcherImpl.closeIntFD(fd1); + throw t; + }
26-08-2015