RFR(S) 8205965: SIGSEGV on write to NativeCallStack::EMPTY_STACK

Martin Buchholz martinrb at google.com
Mon Jul 2 20:12:56 UTC 2018


Below is a possible untested attempt to /Construct On First Use Idiom/ that
doesn't (appear to) allocate, and gets rid of the double construction.

diff --git a/src/hotspot/share/services/mallocSiteTable.hpp
b/src/hotspot/share/services/mallocSiteTable.hpp
--- a/src/hotspot/share/services/mallocSiteTable.hpp
+++ b/src/hotspot/share/services/mallocSiteTable.hpp
@@ -42,7 +42,7 @@ class MallocSite : public AllocationSite

  public:
   MallocSite() :
-    AllocationSite<MemoryCounter>(NativeCallStack::EMPTY_STACK),
_flags(mtNone) {}
+    AllocationSite<MemoryCounter>(NativeCallStack::empty_stack()),
_flags(mtNone) {}

   MallocSite(const NativeCallStack& stack, MEMFLAGS flags) :
     AllocationSite<MemoryCounter>(stack), _flags(flags) {}
diff --git a/src/hotspot/share/services/memTracker.cpp
b/src/hotspot/share/services/memTracker.cpp
--- a/src/hotspot/share/services/memTracker.cpp
+++ b/src/hotspot/share/services/memTracker.cpp
@@ -68,10 +68,6 @@ NMT_TrackingLevel MemTracker::init_track
     os::unsetenv(buf);
   }

-  // Construct NativeCallStack::EMPTY_STACK. It may get constructed twice,
-  // but it is benign, the results are the same.
-  ::new ((void*)&NativeCallStack::EMPTY_STACK) NativeCallStack(0, false);
-
   if (!MallocTracker::initialize(level) ||
       !VirtualMemoryTracker::initialize(level)) {
     level = NMT_off;
diff --git a/src/hotspot/share/services/memTracker.hpp
b/src/hotspot/share/services/memTracker.hpp
--- a/src/hotspot/share/services/memTracker.hpp
+++ b/src/hotspot/share/services/memTracker.hpp
@@ -31,8 +31,8 @@

 #if !INCLUDE_NMT

-#define CURRENT_PC   NativeCallStack::EMPTY_STACK
-#define CALLER_PC    NativeCallStack::EMPTY_STACK
+#define CURRENT_PC   NativeCallStack::empty_stack()
+#define CALLER_PC    NativeCallStack::empty_stack()

 class Tracker : public StackObj {
  public:
@@ -86,9 +86,9 @@ class MemTracker : AllStatic {
 extern volatile bool NMT_stack_walkable;

 #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail &&
NMT_stack_walkable) ? \
-                    NativeCallStack(0, true) :
NativeCallStack::EMPTY_STACK)
+                    NativeCallStack(0, true) :
NativeCallStack::empty_stack())
 #define CALLER_PC  ((MemTracker::tracking_level() == NMT_detail &&
NMT_stack_walkable) ?  \
-                    NativeCallStack(1, true) :
NativeCallStack::EMPTY_STACK)
+                    NativeCallStack(1, true) :
NativeCallStack::empty_stack())

 class MemBaseline;
 class Mutex;
diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp
b/src/hotspot/share/services/virtualMemoryTracker.hpp
--- a/src/hotspot/share/services/virtualMemoryTracker.hpp
+++ b/src/hotspot/share/services/virtualMemoryTracker.hpp
@@ -302,7 +302,7 @@ class ReservedMemoryRegion : public Virt


   ReservedMemoryRegion(address base, size_t size) :
-    VirtualMemoryRegion(base, size), _stack(NativeCallStack::EMPTY_STACK),
_flag(mtNone) { }
+    VirtualMemoryRegion(base, size),
_stack(NativeCallStack::empty_stack()), _flag(mtNone) { }

   // Copy constructor
   ReservedMemoryRegion(const ReservedMemoryRegion& rr) :
diff --git a/src/hotspot/share/utilities/nativeCallStack.cpp
b/src/hotspot/share/utilities/nativeCallStack.cpp
--- a/src/hotspot/share/utilities/nativeCallStack.cpp
+++ b/src/hotspot/share/utilities/nativeCallStack.cpp
@@ -28,8 +28,6 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/nativeCallStack.hpp"

-const NativeCallStack NativeCallStack::EMPTY_STACK(0, false);
-
 NativeCallStack::NativeCallStack(int toSkip, bool fillStack) :
   _hash_value(0) {

diff --git a/src/hotspot/share/utilities/nativeCallStack.hpp
b/src/hotspot/share/utilities/nativeCallStack.hpp
--- a/src/hotspot/share/utilities/nativeCallStack.hpp
+++ b/src/hotspot/share/utilities/nativeCallStack.hpp
@@ -53,7 +53,10 @@
  */
 class NativeCallStack : public StackObj {
  public:
-  static const NativeCallStack EMPTY_STACK;
+  inline static const NativeCallStack& empty_stack() {
+    static const NativeCallStack EMPTY_STACK(0, false);
+    return EMPTY_STACK;
+  }

  private:
   address       _stack[NMT_TrackingStackDepth];


On Mon, Jul 2, 2018 at 12:41 PM, Zhengyu Gu <zgu at redhat.com> wrote:

> Hi Martin,
>
>
> On 07/02/2018 03:26 PM, Martin Buchholz wrote:
>
>> Zhengyu,
>>
>> Thanks for fixing this!
>>
>> I would have tried to use /Construct On First Use Idiom/
>> https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
>> but nothing here is easy, unlike in Java with its static finals.
>> (and I'm not (yet) a hotspot engineer)
>>
>
> Thanks for the link.
>
> However, this pattern does not apply here, since we *cannot* allocate any
> objects at this point.
>
> Hotspot disables global new operator, and allocates any CHeapObj here will
> loop back to initialize NMT (when it is on). We have to workaround this
> problem in several places, see comments in services/mallocSiteTable.hpp,
> for an example.
>
> Thanks,
>
> -Zhengyu
>
>
>
>>
>> On Fri, Jun 29, 2018 at 6:04 AM, Zhengyu Gu <zgu at redhat.com <mailto:
>> zgu at redhat.com>> wrote:
>>
>>     Hi,
>>
>>     clang-6.0 and above, can deduce that NativeCallStack::EMPTY_STACK is
>>     all zeros, and since it is a static constant, it places the object
>>     in the read-only BSS data section.
>>
>>     To workaround static initialization ordering issue, NMT has to
>>     ensure EMPTY_STACK is initialized before turns itself on, which can
>>     happen in the middle of initialization of other static objects. In
>>     this case, it causes SIGSEGV while try to write to the read-only
>> memory.
>>
>>     The solution is to make EMPTY_STACk private and non-constant, but
>>     hands out constant version.
>>
>>     Bug: https://bugs.openjdk.java.net/browse/JDK-8205965
>>     <https://bugs.openjdk.java.net/browse/JDK-8205965>
>>     Webrev: http://cr.openjdk.java.net/~zgu/8205965/webrev.00/
>>     <http://cr.openjdk.java.net/~zgu/8205965/webrev.00/>
>>
>>     Test:
>>
>>        hotspot_nmt on Linux 64 (fastdebug and release)
>>
>>     Thanks,
>>
>>     -Zhengyu
>>
>>
>>


More information about the hotspot-runtime-dev mailing list