-
Notifications
You must be signed in to change notification settings - Fork 728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix code cache segment race condition #18212
Conversation
3e285c1
to
1170e8e
Compare
@joransiu Could you please review this code cache race fix? Thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
jenkins test sanity zlinux jdk21 |
When a new code cache needs to be allocated, first the VM allocates a memory segment and then the JIT allocates a TR::CodeCache structure. Finally, the JIT writes a pointer to the TR::CodeCache structure at the beginning of the memory segment. After the code cache segment has been added to the corresponding VM segment list, but before the JIT had the chance to write the TR::CodeCache pointer, a Java application thread could inquire about memory consumption stats (with MXBeans) which could lead to the VM reading a random value for the TR::CodeCache pointer and crash when dereferencing the bad pointer. The solution is to write a NULL pointer at the begining of the code cache segment as soon as that segment is allocated. Thus, a third party could see either NULL (which is checked against by the reader) or a valid TR::CodeCache pointer. The solution assumes that reads/writes of pointers are atomic on all supported platforms (i.e. 'tearing' is not possible when the values to be written/read are naturaly aligned). Signed-off-by: Marius <[email protected]>
1170e8e
to
16b1a33
Compare
jenkins test sanity zlinux jdk21 |
I changed the code according to the suggestions.
This happens in the OMR code. However, because it's the same thread that creates/initializes the segment and sets the TR:CodeCache pointer at the beginning of the segment, there is no need for another write barrier. |
There is never a need for barriers in a single thread. The case I'm concerned about is another thread getting hold of the pointer and not seeing the correct contents of the structure due to a missing barrier. Given that the cost of the barrier is essentially nothing compared to the rest of the code, I'd err on the side of safety - missing barriers are almost impossible to debug in the field. |
I opened eclipse-omr/omr#7129 for issuing a write barrier before writing the TR::CodeCache pointer at the beginning of the memory segment. |
jenkins test sanity xlinux jdk8 |
Tests have passed |
`allocateVirtualMemorySegmentInListInternal` has been changed to write NULL into the code cache segment in eclipse-openj9#18212. The change does not include `omrthread_jit_write_protect_disable` and `omrthread_jit_write_protect_enable` calls before and after writing to the memory, which results in the crash on Apple Silicon Mac. This commit inserts `omrthread_jit_write_protect_disable` and `omrthread_jit_write_protect_enable` appropriately. Signed-off-by: Akira Saitoh <[email protected]>
This change introduced build failures on AArch64 macOS. PR #18233 fixes it. Nightly build failure at
|
When a new code cache needs to be allocated, first the VM allocates a memory segment and then the JIT allocates a TR::CodeCache structure. Finally, the JIT writes a pointer to the TR::CodeCache structure at the beginning of the memory segment.
After the code cache segment has been added to the corresponding VM segment list, but before the JIT had the chance to write the TR::CodeCache pointer, a Java application thread could inquire about memory consumption stats (with MXBeans) which could lead to the VM reading a random value for the TR::CodeCache pointer and crash
when dereferencing the bad pointer.
The solution is to write a NULL pointer at the begining of the code cache segment as soon as that segment is allocated. Thus, a third party could see either NULL (which is checked against by the reader) or a valid TR::CodeCache pointer.