RFR JDK-8021954 VM SIGSEGV during classloading on MacOS; hs_err_pid file produced
Christian Thalinger
christian.thalinger at oracle.com
Tue Aug 27 10:49:12 PDT 2013
On Aug 27, 2013, at 5:44 AM, Lois Foltan <lois.foltan at oracle.com> wrote:
>
> On 8/27/2013 7:31 AM, David Holmes wrote:
>> On 27/08/2013 6:01 PM, Mikael Gerdin wrote:
>>> On 2013-08-27 04:41, David Holmes wrote:
>>>> On 27/08/2013 4:36 AM, Lois Foltan wrote:
>>>>> Please review the following fix:
>>>>>
>>>>> Internal webrev:
>>>>>
>>>>> http://cr.openjdk.java.net/~coleenp/bug_jdk8021954/
>>>>>
>>>>> Bug: VM SIGSEGV during classloading on MacOS; hs_err_pid file produced &
>>>>> runtime/6878713/Test6878713.sh fails on mac
>>>>>
>>>>> bug links at: https://bugs.openjdk.java.net/browse/JDK-8021954
>>>>> https://bugs.openjdk.java.net/browse/JDK-8022140
>>>>>
>>>>> Summary of fix:
>>>>> On MacOS, currently Hotspot is built specifying the -fcheck-new
>>>>> command line option to the llvm-g++ compiler.
>>>>> The -fcheck-new option directs the compiler to "check that the
>>>>> pointer returned by |operator new| is non-null
>>>>> before attempting to modify the storage allocated." The clang++
>>>>> compiler does not support the
>>>>> -fcheck-new option. To obtain similiar functionality when
>>>>> building Hotspot with clang++, empty exception
>>>>> throw() specifications must be added to all user-defined operator
>>>>> new()'s.
>>>>
>>>> We just spotted something related in the PPC64 port and were going the
>>>> other way or removing these "spurious" throw() declarations.
>>>>
>>>> But this seems really ugly - is there really a need to specialize this
>>>> for clang and use NOEXCEPT to hide it? Shouldn't all C++ compilers
>>>> honour the nothrow() semantics?
>>>>
>>>> That said I thought we already handled this using the "const
>>>> std::nothrow_t& nothrow_constant" where needed? Our other operator new
>>>> implementations shouldn't return NULL but will abort.
>>>>
>>>> So why do we need -fcheck-new or this empty throw() ?
>>>
>>> I guess that if the C++ compiler knows that operator new() will throw an
>>> exception if an allocation fails then it doesn't need to emit code to
>>> explicitly avoid calling the constructor.
>>
>> Yes that is what happens, but why do _we_ need it when ...
>>
>>> If we declare operator new() with an empty throw() we will also inform
>>> the compiler that new can't throw an exception and therefore the
>>> compiler needs to explicitly handle failed allocations.
>>
>> ... we have two kinds of operator new implementations (or at least we _should_ only have two kinds):
>>
>> 1. Will abort on OOM (either ResourceArea exhaustion or Stack exhaustion) and so never returns NULL
>> 2. Can return NULL and uses std::nothrow to indicate that
>>
>> So we should not need this if the nothrow is acting as I think it should. Have we missed places where nothrow is needed? Do we have errant operator new definitions unrelated to the allocation base classes?
> Hi David,
>
> I think there may be some confusion about what std::nothrow_t is actually doing. It provides a mechanism to overload operator new & delete in order to direct the compiler to prefer a function definition that also should contain an empty "throw()" specification. Take for example the standard definition of the global ::operator new(). It actually looks like:
> void * operator new (std::size_t) throw (std::bad_alloc)
> void * operator new (std::size_t, const std::nothrow_t &) throw ()
> When the std::nothrow_t parameter is passed to the global ::operator new() the invoked function is the one that also contains an empty throw() specification. It is due to this empty throw() specification that directs or triggers the C++ compiler to generate the detection of NULL constructor prologue. Specifying only the std::nothrow_t parameter to a class member user-defined ::operator new() does not indicate to a C++ compiler that the function does not throw an exception. According to the c++98 standard, a function that will throw no exceptions should be delcared with an empty "throw()" list specification. When first experimenting with a fix, I did just try to overload Hotspot's user-defined operator new() with the std:nothrow_t parameter. As expected, the mere presence of this parameter did not trigger the clang++ compiler to generate NULL detection constructor prologue code. Unfortunately, probably due to legacy code, some C++ compilers behave differently. For example, I did confirm with Solaris C++ development, the Solaris C++ by default always generates constructor prologue code that detects NULL for class member user-defined operator new() even in a throw situation. G++ provides the -fcheck-new command line option. It is due to these differences of behavior or Hotspot's build specification of -fcheck-new that has led us to believe that std::nothrow_t was providing something that it is not.
>
> That said, I would also prefer what you propose, deciding on two kinds of operator new()'s that can be defined. I did examine all of the user-defined operator new()'s within the code and I determined that only a very small number possibly could not return NULL. Given this, factored in with the historical reliance on -fcheck-new for the g++ compilers, I decided the safe route for JDK 8 was to introduce the NOEXCEPT macro.
Why can't we use throw() with all compilers? Just because we are using -fcheck-new for GCC?
-- Chris
>
> Lois
>>
>> David
>> -----
>>
>>> The g++ man page states:
>>>
>>> -fcheck-new
>>> Check that the pointer returned by "operator new" is
>>> non-null before attempting to modify the storage allocated. This check
>>> is normally unnecessary because the C++ standard specifies that
>>> "operator new" will only return 0 if it is declared throw(),
>>> in which case the compiler will always check the return value even
>>> without this option. In all other cases, when "operator new"
>>> has a non-empty exception specification, memory exhaustion
>>> is signalled by throwing "std::bad_alloc". See also new (nothrow).
>>>
>>> /Mikael
>>>
>>>>
>>>> Thanks,
>>>> David
>>>>
>>>>> Tests:
>>>>>
>>>>> Solaris: built fastdebug & product images
>>>>> Linux: built fastdebug & product images
>>>>> MacOS: built fastdebug & product images using llvm-g++ - ran
>>>>> JTREG
>>>>> built fastdebug & product images using clang++ -
>>>>> ran JTREG, JCK vm & lang, vm.quick.testlist (in progress)
>>>>> Windows: built fastdebug & product images with VS2010
>>>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/attachments/20130827/0f15eaed/attachment.html
More information about the hotspot-runtime-dev
mailing list