JDK-4647546 : Hotspot is using single threaded ("MT-unsafe") Solaris functions
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: sparc
  • Submitted: 2002-03-05
  • Updated: 2023-01-04
  • Resolved: 2002-05-02
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.
1.4.1 hopperFixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
The Solaris versions of Hotspot are not using the MT-safe versions of certain OS functions in some cases. This may lead to subtle failures in a multithreaded context. I complete survey of Hotspot should be conducted to identify all occurances of this problem and each function's MT-safe counterpart must be substituted while also implementing any special buffering requirements that are exposed.

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: hopper FIXED IN: hopper INTEGRATED IN: hopper

WORK AROUND No known workaround for this problem except avoidance of multi-threaded use of the JNI methods that use the MT-unsafe VM calls and it's difficult to know if even this restriction could be guaranteed as the core libraries probably make use of these VM interfaces. This turned out to be a mistaken assumption, see the evaluation. ###@###.### 2002-04-29

SUGGESTED FIX For 1.4.1 all nonreentrant system routine usage within the VM has been eliminated except for the (unused) JVM_* routines described in the evaluation. For 1.4.2 these JVM_* routines will be removed from the export defined by jvm.h in both the VM and library workspaces. This is bug 4674698. If 1.4.2 requirements are defined such that reentrant versions of these VM entrypoints are required then those will be added as part of the new bug. ###@###.### 2002-04-29

EVALUATION A survey of the nonreentrant Unix routines referenced in the VM source was conducted and it turned up the following uses: ====== ctime ====== ./share/vm/runtime/os.cpp: st->print("Local Time = %s", asctime(ltime)); /* ctime() puts a '\n' at the end */ ====== localtime ====== ./share/vm/runtime/os.cpp: ltime = localtime(&long_time); ====== gethostbyname ====== ./os/win32/agent/SwDbgSrv.cpp: struct hostent* myInfo = gethostbyname(myname); ./os/linux/vm/hpi_linux.hpp: return ::gethostbyname(hostname); ./os/solaris/vm/hpi_solaris.hpp: return ::gethostbyname(hostname); ====== gethostbyaddr ====== ./os/linux/vm/hpi_linux.hpp: return ::gethostbyaddr(name, len, type); ./os/solaris/vm/hpi_solaris.hpp: return ::gethostbyaddr(name, len, type); ====== getservbyname ====== ./os/linux/vm/hpi_linux.hpp: return ::getprotobyname(name); ./os/solaris/vm/hpi_solaris.hpp: return ::getprotobyname(name); ====== readdir ====== ./os/win32/vm/os_win32.cpp:os::readdir(DIR *dirp) == argument handling: no need for reentrant version? ./share/vm/runtime/arguments.cpp: while ((entry = os::readdir(dir)) != NULL) { ./os/linux/vm/os_linux.inline.hpp:inline struct dirent* os::readdir(DIR* dirp) ./os/linux/vm/os_linux.inline.hpp: return ::readdir(dirp); ./os/solaris/vm/os_solaris.inline.hpp:inline struct dirent* os::readdir(DIR* dirp) ./os/solaris/vm/os_solaris.inline.hpp: return ::readdir(dirp); ./share/vm/runtime/os.hpp: static struct dirent* readdir(DIR* dirp); ====== getlogin ====== ====== getpwent ====== ====== getnetbyname ====== ====== getnetbyaddr ====== ====== strtok ====== ====== gmtime ====== ====== getservbyport ====== ====== getprotobyname ====== ====== getrpcbyname ====== ====== getrpcbynumber ====== ====== getrpcent ====== ====== ctermid ====== ====== tmpnam ====== ====== getpwnam ====== ====== getpwuid ====== ====== getspent ====== ====== fgetspent ====== ====== getspnam ====== ====== getgrnam ====== ====== getgrgid ====== ====== getnetgrent ====== ====== getrpcbyname ====== ====== tempnam ====== ====== fgetpwent ====== ====== fgetgrent ====== ====== ecvt ====== ====== gcvt ====== ====== getservent ====== ====== gethostent ====== ====== getgrent ====== ====== fcvt ====== The worrisome routines are those used by exported VM functions that might be called in a multithreaded context: JVM_GetHostByAddr() JVM_GetHostByName() JVM_GetProtoByName() A search of the JDK sources (thanks Mark Reinhold!) showed that only networking libraries are making use of these functions and the networking code is already platform aware and for Unix platforms the VM functions are avoided and more direct libc calls are used instead. These exported routines are documented in the following JDK header file: src/share/javavm/export/jvm.h This header file needs to be updated with warning comments about the dangerous routines listed above. The remaining uses of nonrentrant libc functions are either single threaded (e.g. "argument parsing") or in contexts where we aren't too concerned about an additional failure (the VM fatal error path). Provisions can be made to use the corresponding reentrant versions of these routines without too much difficulty. ###@###.### 2002-04-15 As was pointed out by a reviewer, the fact that the VM uses readdir(), for example, in its argument handling and doesn't present a hazard of corruption through multithreading within the VM doesn't mean it's safe to use this routine. That is, if we try not to distinguish between application vs system code in a a process and assume that anybody embedding a VM may use nonreentrant system routines, then the rule becomes *never use the nonreentrant version, period*. So the use of readdir() mentioned above is being modified to use readdir_r() instead. Also, I wasn't clear about the list of nonreentrant routines that the VM was checked for. Here is the complete list used for the survey: asctime ctermid ctime ecvt fcvt fgetgrent fgetpwent fgetspent gcvt getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetgrent getprotobyname getpwent getpwnam getpwuid getrpcbyname getrpcbyname getrpcbynumber getrpcent getservbyname getservbyport getservent getspent getspnam gmtime localtime rand readdir strtok tempnam tmpnam ###@###.### 2002-04-24