United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6984762 Invalid close of file descriptor '-1' in findZoneinfoFile
JDK-6984762 : Invalid close of file descriptor '-1' in findZoneinfoFile

Details
Type:
Bug
Submit Date:
2010-09-14
Status:
Resolved
Updated Date:
2012-03-20
Project Name:
JDK
Resolved Date:
2011-10-18
Component:
core-libs
OS:
linux
Sub-Component:
java.util:i18n
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
6u21
Fixed Versions:

Related Reports
Backport:
Backport:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01, mixed mode)

Note: this also occurs in 6u21 but it is not the version we are recommending at this point.


ADDITIONAL OS VERSION INFORMATION :
Linux <hostname obscured> 2.6.18-128.el5 #1 SMP Wed Dec 17 11:41:38 EST 2008 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
When a java.util.Date is converted to a String the TimeZone is needed. During the retrieval of the timezone information the native method repeatedly tries to close the file descriptor number -1 which causes an error with EBADF.

We are running with the JRE embedded and sandboxed within a database server with full control of all system calls (such as close()).

Looking at the source for findZoneinfoFile() in TimeZone_md.c we see the fd initialized to -1 at the top of the method. Further down we recursively mill through the directory entries at each level in the big while loop. When we finish with a level we cleanup, including a file close:
    if (fd != 0) {
	(void) close(fd);
    }

Note that the close checks for fd != 0 so we incorrectly attempt to close a bad file descriptor (for timezones we are not using no file is opened). The fd should either be initialized to 0 or the close check should exclude -1 as well.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Outside of the Sybase ASE server the equivalent java call is simply:

public static void doit()
{
        java.util.Date d = new java.util.Date()
        System.out.println( d );
}

We go into the native method TimeZone.getSystemTimeZoneID at this point
main[1] where
  [1] java.util.TimeZone.setDefaultZone (TimeZone.java:559)
  [2] java.util.TimeZone.getDefaultRef (TimeZone.java:550)
  [3] java.util.Date.normalize (Date.java:1,193)
  [4] java.util.Date.toString (Date.java:1,027)
  [5] java.lang.String.valueOf (String.java:2,838)
  [6] java.io.PrintStream.println (PrintStream.java:788)
  [7] Foo.doit (Foo.java:4)
  [8] Foo.main (Foo.java:9)

Everything is happening under the covers when doing the timezone lookup
(gdb) where
#0  0x0000000001c8d406 in pci_coma (timeout=0) at /marslinux3_imet_eng/asebharani_wtenhave_vu/calm/svr/sql/generic/pci/bridge/bridge.c:1553
#1  0x00002aaaaee2c25a in pca_close (func=0x316be0d950 <close>, fd=-1) at /marslinux3_imet_eng/asebharani_wtenhave_vu/calm/svr/sql/generic/pci/plugins/jvm/hostapi.c:972
#2  0x0000000001cdeb5c in close (fd=-1) at /marslinux3_imet_eng/asebharani_wtenhave_vu/calm/svr/sql/generic/pci/bridge/pciruntime.c:1808
#3  0x00002aaab02e9ebd in findZoneinfoFile () from /marslinux3_imet_eng/asebharani_wtenhave_vu/sybase.64.SMP/shared/JRE-6_0_20_64BIT/lib/amd64/libjava.so
#4  0x00002aaab02e9ed9 in findZoneinfoFile () from /marslinux3_imet_eng/asebharani_wtenhave_vu/sybase.64.SMP/shared/JRE-6_0_20_64BIT/lib/amd64/libjava.so
#5  0x00002aaab02ea1ba in getPlatformTimeZoneID () from /marslinux3_imet_eng/asebharani_wtenhave_vu/sybase.64.SMP/shared/JRE-6_0_20_64BIT/lib/amd64/libjava.so
#6  0x00002aaab02e9f77 in findJavaTZ_md () from /marslinux3_imet_eng/asebharani_wtenhave_vu/sybase.64.SMP/shared/JRE-6_0_20_64BIT/lib/amd64/libjava.so
#7  0x00002aaab02e9b69 in Java_java_util_TimeZone_getSystemTimeZoneID () from /marslinux3_imet_eng/asebharani_wtenhave_vu/sybase.64.SMP/shared/JRE-6_0_20_64BIT/lib/amd64/libjava.so

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
close(fd) should return 0 (success)
ACTUAL -
close(fd) returns -1 with EBADF for a reason

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Foo
        public static void doit() {
                java.util.Date d = new java.util.Date();
                System.out.println(d);
        }

        public static void main(String[] a)
        {
                doit();
        }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Most users will not see this. We have worked around internally but at the cost of masking other potential errors with incorrect file i/o.

                                    

Comments
EVALUATION

Set fd to -1 after fd gets closed.
                                     
2011-09-27



Hardware and Software, Engineered to Work Together