The terminology used in the HotSpot sources are confusing to casual readers and
people who port HotSpot to various platforms, with the choice of terms for
the intial thread vs main thread vs primordial thread. See comments for more
details.
From the licensee......
[Edited stuff]
B) As can be seen from the using code, the intention of the
procedure `os::Linux::is_initial_thread' (and similar ones on the
other platforms) is to check for the primordial thread (the thread
that installed the pthread library) rather than for the initial
thread (the thread that called `JNI_CreateJavaVM'). But the
implementation erroneously checks for the latter (see code).
Before jse 6 the launcher used the primordial thread to create the
jvm, in which case the primordial thread was equal to the initial
thread. So `is_initial_thread' got this case right, but could
fail on client code that did not maintain this invariant.
Since jse 6 the launcher does not use the primordial thread
anymore to create the jvm, but rather uses a delegate thread. So
`os::Linux::is_initial_thread' erroneously considers the initial
thread as the primordial one. It thus fails to properly recognize
the primordial thread that might still enter (despite the launcher
avoiding it) as described in A.
[Edited Stuff]
When `JNI_CreateJavaVM' is called, the `capture_initial_stack'
procedure stores the stack parameters of the current thread to
`_initial_thread_stack_size' and `_initial_thread_stack_bottom' (if it
does anything useful at all. It might also collect nonsense when it
is not called from the primordial thread. Apparently it was designed
for the case that it gets called from the primordial thread). It does
not actually know, whether the calling thread is the primordial one or
not.
The procedure `is_initial_thread' will return `true' exactly if the
stack pointer of the calling thread is within the stack region
determined by `capture_initial_stack'.
The procedure `AttachCurrentThread' tries to record the stack
parameters of the calling thread. It does so using
`record_stack_base_and_size', which in turn calls `is_initial_thread'.
If this returns `true', then `record_stack_base_and_size' will reuse
the cached stack parameters `_initial_thread_stack_...'. Otherwise,
`pthread_getattr_np' will be called on `pthread_self()'.
Now, calling `pthread_getattr_np(pthread_self(), &attr)' within the
primordial thread is undefined, because calling `pthread_self()' is
undefined, because the primordial thread is not a pthread, by
definition.
So if `JNI_CreateJavaVM' was called by a non-primordial thread
(e.g. as done by the launcher in jse 6), subsequent calls to
`AttachCurrentThread' from the primordial thread will lead to
undefined behavior, because the primordial thread will be mistaken for
a non-primordial thread.
It is clear that the only clean solutions are
A) to use a different thread implementation which provides
reliable info on the primordial thread as well,
B) to disallow the primordial thread to enter the vm.
However, it looks as if this can not be cleanly checked
within the code on linux and must be a precondition imposed
on the client.
-----------------------------
people who port HotSpot to various platforms, with the choice of terms for
the intial thread vs main thread vs primordial thread. See comments for more
details.
From the licensee......
[Edited stuff]
B) As can be seen from the using code, the intention of the
procedure `os::Linux::is_initial_thread' (and similar ones on the
other platforms) is to check for the primordial thread (the thread
that installed the pthread library) rather than for the initial
thread (the thread that called `JNI_CreateJavaVM'). But the
implementation erroneously checks for the latter (see code).
Before jse 6 the launcher used the primordial thread to create the
jvm, in which case the primordial thread was equal to the initial
thread. So `is_initial_thread' got this case right, but could
fail on client code that did not maintain this invariant.
Since jse 6 the launcher does not use the primordial thread
anymore to create the jvm, but rather uses a delegate thread. So
`os::Linux::is_initial_thread' erroneously considers the initial
thread as the primordial one. It thus fails to properly recognize
the primordial thread that might still enter (despite the launcher
avoiding it) as described in A.
[Edited Stuff]
When `JNI_CreateJavaVM' is called, the `capture_initial_stack'
procedure stores the stack parameters of the current thread to
`_initial_thread_stack_size' and `_initial_thread_stack_bottom' (if it
does anything useful at all. It might also collect nonsense when it
is not called from the primordial thread. Apparently it was designed
for the case that it gets called from the primordial thread). It does
not actually know, whether the calling thread is the primordial one or
not.
The procedure `is_initial_thread' will return `true' exactly if the
stack pointer of the calling thread is within the stack region
determined by `capture_initial_stack'.
The procedure `AttachCurrentThread' tries to record the stack
parameters of the calling thread. It does so using
`record_stack_base_and_size', which in turn calls `is_initial_thread'.
If this returns `true', then `record_stack_base_and_size' will reuse
the cached stack parameters `_initial_thread_stack_...'. Otherwise,
`pthread_getattr_np' will be called on `pthread_self()'.
Now, calling `pthread_getattr_np(pthread_self(), &attr)' within the
primordial thread is undefined, because calling `pthread_self()' is
undefined, because the primordial thread is not a pthread, by
definition.
So if `JNI_CreateJavaVM' was called by a non-primordial thread
(e.g. as done by the launcher in jse 6), subsequent calls to
`AttachCurrentThread' from the primordial thread will lead to
undefined behavior, because the primordial thread will be mistaken for
a non-primordial thread.
It is clear that the only clean solutions are
A) to use a different thread implementation which provides
reliable info on the primordial thread as well,
B) to disallow the primordial thread to enter the vm.
However, it looks as if this can not be cleanly checked
within the code on linux and must be a precondition imposed
on the client.
-----------------------------
- relates to
-
JDK-6516521 Doc: should document about the primordial thread attaching to the VM.
- Resolved