Fix: Heap Corruption from Ownable Synchronizers Lists with Concurrent Scavenger - #6633
Conversation
|
@dmitripivkine @amicic please review |
With Concurrent Scavenger, we may end up with unflushed Ownabele Sync. buffers which can lead to heap corruption. Multiple crashes and assertion have been reported as a result of this, for instance: ``` j9mm.141 * ** ASSERTION FAILED ** at ./OwnableSynchronizerObjectBuffer.cpp:100: ((false)) ``` ``` ** ASSERTION FAILED ** at ./Scavenger.cpp:1659: ((false)) ``` ``` Corruption in Evacuate at 0000005020E395F8: calculated object size 344152650780 larger then available 3172872, Forwarded Header at 00000050322FE8A8 ``` ``` * ** ASSERTION FAILED ** at ../../../gc_glue_java/MarkingDelegate.hpp:123: ((false && ((UDATA)0x99669966 == clazz->eyecatcher))) ``` Ownable buffers are flushed: 1. At the start of a global cycle when we acquire exlusive access. 2. Scavenger will flush Ownable buffers for participating threads, as threads complete a cycle, `scavengerRootScanner.flush(env);` . In terms of #⁠2, the scheduler may dispatch different threads for different phases of CS; Ownable lists are built during scan phase, however buffers are only flushed during the final phase. Hence, threads that don't participate in the last phase (but participated in prior phases) may still have buffers which need to be flushed. Typically, this isn't an issue because all buffers will be flushed as we acquire exclusive for global (#⁠1). The problem arises because there's still a possibility to miss flushing the buffers: when we complete a CS cycle as part of a global cycle (i.e CS cycle in STW through `MM_ParallelGlobalGC::completeExternalConcurrentCycle`). In which case, we're already past acquiring exlusive (#⁠1) and scavenger (#⁠2) will miss to flush threads that don't participate in the final phase of CS (but built lists in prior phases). A simple workaround is to invoke `GC_OMRVMInterface::flushNonAllocationCaches(env);` in this specific case. This will ensure all thread buffers are flushed. This should be revisited and a better solution should be adopted for Scavenger to handle this. Signed-off-by: Salman Rana <salman.rana@ibm.com>
|
Debug trace points without this change: These trace points show:
Since thread 3 is not selected, its buffer won't be flushed during the final phase. |
|
ready to be merged - could you please proceed @0xdaryl |
|
jenkins build all |
Is there an issue for the long-term solution (for tracking purposes)? Can it be linked to this PR? |
|
We will actually be removing ownable sync. lists all together in the near future, we can revert this change after that work is completed. It is being tracked here: eclipse-openj9/openj9#15193 with the new implementation currently under review Edit: fixed PR issue link |
|
eclipse-openj9/openj9#1519 seems unrelated. Should it be eclipse-openj9/openj9#15193? |
In terms of Ownable Sync., we can revert this change. However, there is still a fundamental issue(?) in terms of "consistency" with different threads being selected |
|
I'll be discussing with @amicic and will open an issue if required. |
Yup, I messed that up. Thanks! |
Relates to eclipse-omr#6633 Currently, we rely on the global collector to flush ownable sync. buffers when we complete an external concurrent scavenge cycle during a global collection. This not optimal as it requires all the threads to be iterated and flushed. Furthermore, it is Scavenger's responsibility to flush buffers for the participating GC threads in a CS phase. Signed-off-by: Salman Rana <salman.rana@ibm.com>
Relates to eclipse-omr#6633 Currently, we rely on the global collector to flush ownable sync. buffers when we complete an external concurrent scavenge cycle during a global collection. This not optimal as it requires all the threads to be iterated and flushed. Furthermore, it is Scavenger's responsibility to flush buffers for the participating GC threads in a CS phase. Signed-off-by: Salman Rana <salman.rana@ibm.com>
Relates to eclipse-omr#6633 Currently, we rely on the global collector to flush ownable sync. buffers when we complete an external concurrent scavenge cycle during a global collection. This not optimal as it requires all the threads to be iterated and flushed. Furthermore, it is Scavenger's responsibility to flush buffers for the participating GC threads in a CS phase. Signed-off-by: Salman Rana <salman.rana@ibm.com>
With Concurrent Scavenger, we may end up with unflushed Ownabele Sync. buffers which can eventually lead to a heap corruption. Multiple crashes and assertion have been reported as a result of this, for instance:
For Concurrent Scavenger, the Ownable buffers are flushed:
At the start of a global cycle when we acquire exclusive access. https://github.com/eclipse/omr/blob/e70cf35e07900aa3dcf6f5c68f895094faadaca1/gc/base/standard/ConcurrentGC.hpp#L379
Scavenger will flush Ownable buffers for participating threads, as
threads complete a cycle,
scavengerRootScanner.flush(env);.https://github.com/eclipse/omr/blob/e70cf35e07900aa3dcf6f5c68f895094faadaca1/gc/base/standard/Scavenger.cpp#L5634
In terms of #2, the scheduler may dispatch different threads for different phases of CS; Ownable lists are built during scan phase, however buffers are only flushed during the final phase. Hence, threads that don't participate in the last phase (but participated in prior phases) may still have buffers which need to be flushed. Typically, this isn't an issue because all buffers will be flushed as we acquire exclusive for global (#1).
The problem arises as there's still a possibility to miss flushing the buffers: when we complete a CS cycle as part of a global cycle (i.e CS cycle in STW through
MM_ParallelGlobalGC::completeExternalConcurrentCycle). In which case, we're already past acquiring exlusive (#1) and scavenger (#2) will miss to flush threads that don't participate in the final phase of CS (but built lists in prior phases).A simple workaround is to invoke
GC_OMRVMInterface::flushNonAllocationCaches(env);in this specificcase. This will ensure all thread buffers are flushed. This should be revisited and a better solution should be adopted for Scavenger to handle this.
Signed-off-by: Salman Rana salman.rana@ibm.com