-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8292201: serviceability/sa/ClhsdbThreadContext.java fails with "'Thread "Common-Cleaner"' missing from stdout/stderr" #10090
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
Conversation
|
👋 Welcome back cjplummer! A progress list of the required criteria for merging this PR into |
|
@plummercj this pull request can not be integrated into git checkout 8292201_sa_alignment
git fetch https://git.openjdk.org/jdk master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
|
@plummercj The following labels will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command. |
| public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger { | ||
| private RemoteDebugger remoteDebugger; | ||
| private RemoteThreadFactory threadFactory; | ||
| private boolean unalignedAccessesOkay = false; |
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.
After getting rid of the readCInteger and readJLong overrides below, unalignedAccessesOkay is no longer needed. The DebuggerBase superclass understands the alignment requirements.
|
/label remove core-libs |
|
@AlanBateman |
| long pageMask = ~(pageSize - 1); | ||
| if ((address & pageMask) != ((address + 4) & pageMask)) { |
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.
This looks a bit over-complicated.
Maybe something like
long pageMask = pageSize - 1; if ((address & pageMask) > (pageSize - 8)) { return false; }
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.
I tinkered with this code quite a bit before I had something that both worked and I liked. I don't know that your approach is actually any simpler, and at the moment I still prefer mine, but that might just be because I'm more familiar with it. However, it does seem that there should be a more elegant way of doing this.
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.
Your code works only for the exact case - address of 64bit value points to the last 32bit of the page.
My idea is to use more generic approach - check that the whole value is in the page, i.e. this is special case of more common
boolean canUsePageCacheForRead(long address, int bits) {
long pageMask = pageSize - 1;
return ((address & pageMask) <= (pageSize - bits/8));
}
But I have no strong objections, feel free to keep your version
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.
Your code works only for the exact case - address of 64bit value points to the last 32bit of the page.
That's the only case we need to worry about. Any others would have already failed the alignment check.
|
@plummercj This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 29 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
| if (address % 4 == 0) { | ||
| return; | ||
| } | ||
| } |
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.
The indent above has to be 2.
sspitsyn
left a comment
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.
This looks okay to me.
Thanks,
Serguei
|
Thanks Alex and Serguei! /integrate |
|
Going to push as commit 767262e.
Your commit was automatically rebased without conflicts. |
|
@plummercj Pushed as commit 767262e. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
While dumping all registers (and doing a findpc on each), the following exception occurred for r8:
This exception is the result of using PointerFinder ("findpc") on invalid address that starts on the last 32-bit word of a page. "page" in this case is referring to a page in SA's PageCache, which are always 4k in size. Note findpc is frequently done using an invalid address. In this test case it is being called on each x64 register, which could contain anything. findpc relies on getting some sort of AddressException when this happens, and will then say the address points to something that is unknown. However, in the case of the address pointing to the last 32-bot word of a page, it results in an ArrayIndexOutOfBoundsException when the page cache tries to read past the end of the page. This is happening in Page.getLong(), which you can see in the stack trace.
The main culprit here is some weakening of the alignment checks being done. The alignment check should have resulted in an UnalignedAddressException long before we ever got to Page.getLong(). However, we have the following override, which is allowing the unaligned address to pass the alignment check.
This allows a pointer to a 64-bit value to only be 32-bit aligned. But there's more to it than that. I modified ClhsdbFindPC.java to fetch a tid (a thread address), and did a findpc on the address OR'd with 0xffc.
findpcuses PointerFinder. This forced a read of a 64-bit value that starts in the last 32-bits of a page. It passed on linux-x64 but failed on windowx-x64 in the same manner described in the description of this CR. The difference between the two implementations is that windows relies on the default implementation of DebuggerBase.readCInteger() whereas linux has an override. DebuggerBase.readCInteger() does the following:There is an alignment check here, but it is the "relaxed" override shown above, which allows 64-bit addresses on 32-bit boundaries. The override in LinuxDebuggerLocal is:
Although there is a relaxed alignment check here also, the code that reads from the address does not assume all the bytes are on the same page. It uses readBytes() intead of cache.getLong(), so it won't run into the PageCache issue with reading a 64-bit value that starts in the last 32-bit word of a page.
I think the introduction of these relaxed alignment checks has a muddled history, probably made more muddled by ports cloning code that maybe wasn't necessary. Probably also initial fixes (the relaxed alignment check) seemed to work at first, but later the PageCache issue was discovered, leading to readBytes() workaround in the LinuxDebuggerLocal.readCInteger() override, but was not also done on other ports (so we got this CR for windows).
For 64-bit support it's clear this easing of the 64-bit alignment is not needed, and getting rid of it would result in the proper UnalignedAddressException being thrown. The question is whether it is still needed for 32-bit x86, and if so is it needed on all ports.
I can't test linux-x86, so I can't tell if it still allows 64-bit values on 32-bit aligned addresses, so for now I'll assume it does. So the approach being taken is whenever an address of a 64-bit type points to the last 32-bit word of a page, use readBytes() to get the 64-bit value one byte at a time. It still uses the page cache in the end, but it doesn't try to get all 8 bytes from the same page. Note for 64-bit systems, the conditoin will never arise because of the removal of the relaxed alignment check. Instead there will be an UnalignedAddressException at an early point when the alignment check is made.
One windfall of this change is now we always read 64-bit values from the page cache in a way that is much more efficient than reading a byte at a time. This has resulted in about a 25% performance improvement in a test I have that does a heap dump.
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/10090/head:pull/10090$ git checkout pull/10090Update a local copy of the PR:
$ git checkout pull/10090$ git pull https://git.openjdk.org/jdk pull/10090/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 10090View PR using the GUI difftool:
$ git pr show -t 10090Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/10090.diff