-
Notifications
You must be signed in to change notification settings - Fork 5.8k
8340491: Thread stack-base assertion should report which thread has the un-set stack #21102
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 dholmes! A progress list of the required criteria for merging this PR into |
@dholmes-ora 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 129 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 |
@dholmes-ora The following label 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 list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
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.
Looks fine, but could you explain when this is needed?
If it is the current thread that is crashes then we already print the thread info.
If it is crashing when called on another thread, it might be easier to add informative asserts in that sub-system instead. You could for example add a non-asserting getter and perform all relevant checks on the caller side.
Another alternative could be to leverage the VMErrorCallback functionality I introduced a little while ago. With that you can register a callback to be called by the hs_err printer if the current thread crashes. With that you can have much more context about what the calling code was doing and what information that thread has available. That would look something like this (I've not compiled this, so there might be errors Edit: updated the code):
diff --git a/src/hotspot/share/nmt/memMapPrinter.cpp b/src/hotspot/share/nmt/memMapPrinter.cpp
index 5f920b102a9..a2aae39b0ca 100644
--- a/src/hotspot/share/nmt/memMapPrinter.cpp
+++ b/src/hotspot/share/nmt/memMapPrinter.cpp
@@ -44,6 +44,7 @@
#include "runtime/vmThread.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
+#include "utilities/vmError.hpp"
// Note: throughout this code we will use the term "VMA" for OS system level memory mapping
@@ -164,8 +165,29 @@ class CachedNMTInformation : public VirtualMemoryWalker {
/////// Thread information //////////////////////////
+class VMAInspectionErrorCallback : public VMErrorCallback {
+ const void* const _from;
+ const void* const _to;
+ const Thread* const _thread;
+
+public:
+ VMAInspectionErrorCallback(const void* from, const void* to, const Thread* thread) :
+ _from(from), _to(to), _thread(thread) {}
+
+ void call(outputStream* st) override {
+ st->print_cr("Crashing while printing VMA details for " PTR_FORMAT " " PTR_FORMAT " for thread %s with id: %d",
+ p2i(_from),
+ p2i(_to),
+ _thread->name(),
+ _thread->osthread() != nullptr ? _thread->osthread()->thread_id() : 0);
+ }
+};
+
// Given a VMA [from, to) and a thread, check if vma intersects with thread stack
static bool vma_touches_thread_stack(const void* from, const void* to, const Thread* t) {
+ VMAInspectionErrorCallback on_error(from, to, t);
+ VMErrorCallbackMark mark(&on_error);
+
// Java thread stacks (and sometimes also other threads) have guard pages. Therefore they typically occupy
// at least two distinct neighboring VMAs. Therefore we typically have a 1:n relationshipt between thread
// stack and vma.
Note that in this context we do have a ResourceMark, so it should be fine to print the name.
Thanks for the review @stefank !
The assert is firing when |
@@ -532,7 +532,7 @@ class Thread: public ThreadShadow { | |||
|
|||
public: | |||
// Stack overflow support | |||
address stack_base() const { assert(_stack_base != nullptr,"Sanity check"); return _stack_base; } | |||
address stack_base() const DEBUG_ONLY(;) NOT_DEBUG({ return _stack_base; }) |
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 think it is a bit cleaner to "just" outline the checking method like:
thread.hpp:
address stack_base() const { assert_stack_base(); return _stack_base; }
void assert_stack_base() const NOT_DEBUG_RETURN;
thread.cpp:
#ifdef ASSERT
void Thread::assert_stack_base() const {
// Note: can't report Thread::name() here as that can require a ResourceMark which we
// can't use because this gets called too early in the thread initialization.
assert(_stack_base != nullptr, "Stack base not yet set for thread id:%d (0 if not set)",
osthread() != nullptr ? osthread()->thread_id() : 0);
}
#endif
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 is the way we do it in existing code, e.g.
void assert_is_frame_safe(const frame& f) NOT_DEBUG_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.
So many ways to achieve the same thing ...
I would not want assert_stack_base in the public API.
I did need to fix the ifdef though.
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.
DEBUG_ONLY(;)
just triggers me, sorry. We have NOT_DEBUG_RETURN
exactly for this reason: mark the methods that are only defined in debug builds, and shortcut otherwise, without inventing new things :)
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.
Only have a nitpicking comment, see above ^
That was fully understood and I think you are missing my point. I was trying to convey that it might be better to rewrite the calling code to perform its own checks / logging instead of relying on a "low-level" assert in Thread. 2c. |
The calling code is of course being fixed (or at least the cause dealt with one way or another). The point here was to simply enhance the existing assertion to be more informative for the next time it gets triggered. |
Right. And that was what I was curious to know more about because I think there would be better ways to get better diagnostics by changing code there. Anyways, I'll leave you to deal with that in a separate issue. |
Anyone want to add the second review or shall I just abort 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.
Looks good, and useful!
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.
Well, I am still nitpicking about DEBUG_ONLY(;)
, but I can live with it.
This PR is much more complicated than it needs to be.
There's no point in trying to separate the debug/release builds into .cpp/.hpp files if the related functions already put the assert in the header. |
@stefank as mentioned in the description I ran into include file issues referring to |
Thanks for the review @kevinjwalls ! |
OK. Did you consider my bullet (1) at all? |
I re-read the PR and see that this is what you started with and that Thomas requested this to be inlined. |
FTR, I'm not blocking this, I'm just a little annoyed that we unnecessarily (IMHO) uglify the code. |
Okay thanks for the reviews. /integrate |
Going to push as commit 31858fc.
Your commit was automatically rebased without conflicts. |
@dholmes-ora Pushed as commit 31858fc. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Please review this simple enhancement to an assertion so we can identify which thread had the problem.
I had to move the function to the cpp file due to include file issues.
We are limited in what we can print due to this being used very early in the thread initialization process - in particular no ResourceMarks are possible so we can't print the name.
Testing:
Thanks
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/21102/head:pull/21102
$ git checkout pull/21102
Update a local copy of the PR:
$ git checkout pull/21102
$ git pull https://git.openjdk.org/jdk.git pull/21102/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 21102
View PR using the GUI difftool:
$ git pr show -t 21102
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/21102.diff
Webrev
Link to Webrev Comment