JDK-8150460 : (linux|bsd|aix)_close.c: file descriptor table may become large or may not work at all
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux,os_x,aix
  • Submitted: 2016-02-23
  • Updated: 2024-10-15
  • Resolved: 2016-04-25
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 Other
8u441Fixed 9 b116Fixed openjdk8u252Fixed
Related Reports
Relates :  
Description
In linux_close.c - and similarily in bsd_close.c and aix_close.c - an array (fdTable) is used to keep an information record and a mutex per opened file descriptor. This array gets allocated at the start of the process.

In order to guess on the size of the table, getrlimit(RLIMIT_NO_FILE) is used.

There are some problems with this approach:

1) There is no handling for an infinite limit. Depending on what the numerical value is for RLIM_INFINITY, allocation of the file descriptor table may fail at this point (RLIM_INFINITY=-1) or be very small (RLIM_INFINITY=0). This may lead to file descriptors not covered by the whole wakeup mechanism implemented in this file, and hence to hanging threads.

2) For large - but not infinite - values of RLIMIT_NO_FILE, the memory usage is excessive. On Linux x64, each entry in the table is ~ 50Bytes; for a limit of 1000000, this eats up 50MB. Most of this memory is usually never used.


Comments
Fix request (8u): Reason: This fix avoids malloc of up to 50Mb of memory during initial link-loading of libnet (the worst case happens in a runtime where no fd limit is set which is fairly common). The saving is not especially significant when linking libnet.so into OpenJDK8 (although 50Mb /is/ well worth saving). It is much more significant when libnet.a is linked into a Graal native image. See this discussion on the GraalVM dev list for more details https://github.com/oracle/graal/issues/1984 Updated Patch: The patch applies cleanly after adjusting the file paths and minor whitespace and copyright headers differences: http://cr.openjdk.java.net/~adinn/8150460/webrev.00 Testing: tier1 tests pass as before
02-01-2020

URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/ee0a64ae78db User: lana Date: 2016-04-27 18:46:47 +0000
27-04-2016

URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/ee0a64ae78db User: stuefe Date: 2016-04-25 08:09:28 +0000
25-04-2016

The proposed solution: Instead of relying on getrlimit(RLIMIT_NO_FILE), just handle the whole theoretical value range for file descriptors, which is an int and on all our platforms 32bit. Organise the file descritpor table not as linear array but as two dimensional sparse array (64k x 64k), with the second dimension arrays only allocated on demand. This keeps the lookup simple and reduces memory consumption for the typical case that file descriptors are small and handed out by the OS sequentially, while still handling corner cases like large file descriptor values.
24-02-2016