JDK-6942771 : SEGV in ParScanThreadState::take_from_overflow_stack
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 6u19,6u20
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,solaris_10
  • CPU: generic
  • Submitted: 2010-04-10
  • Updated: 2014-10-05
  • Resolved: 2010-04-29
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.
JDK 6 JDK 7 Other
6u20-rev b03Fixed 7Fixed hs16.3Fixed
Related Reports
Relates :  
Relates :  
# A fatal error has been detected by the Java Runtime Environment:
#  SIGSEGV (0xb) at pc=0xfffffd7ffedf4cbd, pid=733, tid=6
# JRE version: 6.0
# Java VM: Java HotSpot(TM) 64-Bit Server VM (16.2-b04 mixed mode solaris-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x9f4cbd]
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp

---------------  T H R E A D  ---------------

Current thread (0x00000000004bd800):  GCTaskThread [stack: 0x0000000000000000,0x0000000000000000] [id=6]

siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000000000000fe8;; 

RAX=0x00000000000007da, RBX=0xfffffd7e8b3e6c60, RCX=0x00000000000007dc, RDX=0x0000000000000001
RSP=0xfffffd7ffaafba00, RBP=0xfffffd7ffaafba60, RSI=0xfffffd7ee75c7890, RDI=0x0000000004f46b90
, R8=0x00000000000001fe, R9=0x0000000000000000, R10=0x00000000015f0010, R11=0xfffffd7e71a0f000, R12=0x0000000000000014, R13=0x0000000000000002, R14=0x00000000004ddc00, R15=0x00000000016f1f98
RIP=0xfffffd7ffedf4cbd, RFLAGS=0x0000000000010202

Top of Stack: (sp=0xfffffd7ffaafba00)
0xfffffd7ffaafba00:   fffffd7ee75c7888 00000000004ddc08
0xfffffd7ffaafba10:   0000000004f46b90 00000000004ddc00
0xfffffd7ffaafba20:   00000000000007da fffffd7fff0e74d4
0xfffffd7ffaafba30:   fffffd7ff67f6fe0 fffffd7fff0e74d4
0xfffffd7ffaafba40:   fffffd7fff0ffb78 fffffd7fff0e0b48
0xfffffd7ffaafba50:   0000000000000000 fffffd7fff0e7472
0xfffffd7ffaafba60:   fffffd7ffaafbb30 fffffd7ffedf554c
0xfffffd7ffaafba70:   0000000004f46b90 fffffd7ffaafbb90
0xfffffd7ffaafba80:   0000000000482410 fffffd7e68f65490
0xfffffd7ffaafba90:   0000000000000011 fffffd7ffeb4736b
0xfffffd7ffaafbaa0:   fffffd7ffaafbac0 000019ce000007da
0xfffffd7ffaafbab0:   000019cf000007da 0000000000482410
0xfffffd7ffaafbac0:   00001cab00000783 00001cab00000784
0xfffffd7ffaafbad0:   000016a300000cf8 000016a300000cf9
0xfffffd7ffaafbae0:   0000000004f46b90 fffffd7ffede3c79
0xfffffd7ffaafbaf0:   00000000004ddc00 00000000004ddc08
0xfffffd7ffaafbb00:   fffffd7ef6eecd18 fffffd7fff0f5410
0xfffffd7ffaafbb10:   0000000004f46c80 0000000004f46c30
0xfffffd7ffaafbb20:   000019ce000007da 0000000004f46dc0
0xfffffd7ffaafbb30:   fffffd7ffaafbbc0 fffffd7ffedf5cff
0xfffffd7ffaafbb40:   fffffd7e68f65490 0000000000000004
0xfffffd7ffaafbb50:   00000000004a3650 00000000004bd800
0xfffffd7ffaafbb60:   0000000000000011 fffffd7fff0f5410
0xfffffd7ffaafbb70:   00000000004b5e50 00000000004ba290
0xfffffd7ffaafbb80:   00000000004ba2a0 00000000004ba678
0xfffffd7ffaafbb90:   00000000004bd800 0000000000495010
0xfffffd7ffaafbba0:   00000000004b9e10 00000000004b9e20
0xfffffd7ffaafbbb0:   00000000004ba1f8 00000000004bef90
0xfffffd7ffaafbbc0:   fffffd7ffaafbc20 fffffd7ffef15958
0xfffffd7ffaafbbd0:   0000000000000000 fffffd7fff0e73cb
0xfffffd7ffaafbbe0:   00000000004bd800 fffffd7fff10d548
0xfffffd7ffaafbbf0:   fffffd7fff182a00 fffffd7ffe8aa3f7 

Instructions: (pc=0xfffffd7ffedf4cbd)
0xfffffd7ffedf4cad:   74 15 4d 8b c8 49 ff c9 4d 89 4f 20 4d 8b 4f 38
0xfffffd7ffedf4cbd:   4b 8b 5c c1 f8 eb 76 4d 8b c8 49 ff c9 4d 89 4f 
;; fffffd7ffedf4cad 74 15                   je     0xfffffffffedf4cc4
;; fffffd7ffedf4caf 4d 8b c8                mov    %r8,%r9
;; fffffd7ffedf4cb2 49 ff c9                dec    %r9
;; fffffd7ffedf4cb5 4d 89 4f 20             mov    %r9,0x20(%r15)
;; fffffd7ffedf4cb9 4d 8b 4f 38             mov    0x38(%r15),%r9
;; ---------------
;; fffffd7ffedf4cbd 4b 8b 5c c1 f8          mov    0xfffffffffffffff8(%r9,%r8,8),%rbx
;; fffffd7ffedf4cc2 eb 76                   jmp    0xfffffffffedf4d3a
;; fffffd7ffedf4cc4 4d 8b c8                mov    %r8,%r9
;; fffffd7ffedf4cc7 49 ff c9                dec    %r9
;; fffffd7ffedf4cca 4d 89 4f ff             mov    %r9,0xffffffffffffffff(%r15)
Stack: [0x0000000000000000,0x0000000000000000],  sp=0xfffffd7ffaafba00,  free space=5ffeabee0000000000000001k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x9f4cbd];;  bool ParScanThreadState::take_from_overflow_stack()+0xbd
V  [libjvm.so+0x9f554c];;  void ParEvacuateFollowersClosure::do_void()+0xbc
V  [libjvm.so+0x9f5cff];;  void ParNewGenTask::work(int)+0x17f
V  [libjvm.so+0xb15958];;  void GangWorker::loop()+0xd8
V  [libjvm.so+0xb15849];;  void GangWorker::run()+0x29
V  [libjvm.so+0x9e3449];;  java_start+0x1f9
C  [libc.so.1+0xd704b]  _thr_slot_offset+0x31b;;  _etext+0x272b3
C  [libc.so.1+0xd7280]  _thr_slot_offset+0x550;;  _etext+0x274e8

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot/hotspot/rev/894b1d7c7e01

EVALUATION http://hg.openjdk.java.net/hsx/hsx19/baseline/rev/0c5c902506a0

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/894b1d7c7e01

EVALUATION Verified in build 1.6.0_20 b03 Tested java -Xmx128M -XX:+UseParNewGC -XX:+ParGCUseLocalOverflow -XX:+ParGCWorkQueueOverflowALot -jar GCBasher.jar -time:300000 whixh asserts against 1.6.0_19 b04 (which is build without fix) and passes against 1.6.0_20 b03

EVALUATION http://hg.openjdk.java.net/hsx/hsx17/master/rev/c475b10a610b

EVALUATION http://hg.openjdk.java.net/hsx/hsx17/baseline/rev/c475b10a610b

EVALUATION You can reproduce it with the following options on any non-product jvm (don't need 64-bit or compressed oops): -XX:+UseParNewGC -XX:+ParGCUseLocalOverflow -XX:+ParGCWorkQueueOverflowALot The _full_seg_size member of the stack is set to the wrong value when pushing the first segment, causing size() to return the wrong value.

EVALUATION As Ramki suspected, it's a bug in the Stack<> code; one of the fields was not being updated properly when transitioning from an empty stack to a non-empty one, or vice-versa. (Per John Coomes) This bug was encountered during testing of 6919368. The origin is in the code changes for 6423256 which have been applied (so far) in the following change sets: Repository=/net/jano2.sfbay/export2/hotspot/ws/16.2/baseline,ChangeSet=a57e60e92559,ChangeRequest=6423256 Repository=/net/jano2.sfbay/export2/hotspot/ws/16.1/baseline,ChangeSet=b67191788e7b,ChangeRequest=6423256 Repository=/java/jdk/ws/hotspot/ws/16.2/master,ChangeSet=a57e60e92559,ChangeRequest=6423256 Repository=/java/jdk/ws/hotspot/ws/16.1/master,ChangeSet=b67191788e7b,ChangeRequest=6423256

SUGGESTED FIX diff --git a/src/share/vm/utilities/stack.hpp b/src/share/vm/utilities/stack.hpp --- a/src/share/vm/utilities/stack.hpp +++ b/src/share/vm/utilities/stack.hpp @@ -148,7 +148,7 @@ void free_segments(E* seg); // Free all segments in the list. inline void reset(bool reset_cache); // Reset all data fields. - DEBUG_ONLY(void verify() const;) + DEBUG_ONLY(void verify(bool at_empty_transition) const;) DEBUG_ONLY(void zap_segment(E* seg, bool zap_link_field) const;) private: diff --git a/src/share/vm/utilities/stack.inline.hpp b/src/share/vm/utilities/stack.inline.hpp --- a/src/share/vm/utilities/stack.inline.hpp +++ b/src/share/vm/utilities/stack.inline.hpp @@ -157,10 +157,11 @@ next = alloc(segment_bytes()); DEBUG_ONLY(zap_segment(next, true);) } + const bool at_empty_transition = is_empty(); _cur_seg = set_link(next, _cur_seg); _cur_seg_size = 0; - _full_seg_size += _seg_size; - DEBUG_ONLY(verify();) + _full_seg_size += at_empty_transition ? 0 : _seg_size; + DEBUG_ONLY(verify(at_empty_transition);) } template <class E> @@ -177,10 +178,11 @@ DEBUG_ONLY(zap_segment(_cur_seg, true);) free(_cur_seg, segment_bytes()); } + const bool at_empty_transition = prev == NULL; _cur_seg = prev; _cur_seg_size = _seg_size; - _full_seg_size -= _seg_size; - DEBUG_ONLY(verify();) + _full_seg_size -= at_empty_transition ? 0 : _seg_size; + DEBUG_ONLY(verify(at_empty_transition);) } template <class E> @@ -208,14 +210,14 @@ #ifdef ASSERT template <class E> -void Stack<E>::verify() const +void Stack<E>::verify(bool at_empty_transition) const { assert(size() <= max_size(), "stack exceeded bounds"); assert(cache_size() <= max_cache_size(), "cache exceeded bounds"); assert(_cur_seg_size <= segment_size(), "segment index exceeded bounds"); assert(_full_seg_size % _seg_size == 0, "not a multiple"); - assert(is_empty() == (size() == 0), "mismatch"); + assert(at_empty_transition || is_empty() == (size() == 0), "mismatch"); assert((_cache == NULL) == (cache_size() == 0), "mismatch"); if (is_empty()) {