8306510: Print number of threads and stack sizes in error reports

Reviewed-by: gziemski, dholmes
This commit is contained in:
Thomas Stuefe 2023-05-02 12:18:23 +00:00
parent a8d16dea8e
commit ea9201f420
4 changed files with 32 additions and 10 deletions

View file

@ -1515,12 +1515,13 @@ void JavaThread::print_on_error(outputStream* st, char *buf, int buflen) const {
st->print("%s \"%s\"", type_name(), get_thread_name_string(buf, buflen)); st->print("%s \"%s\"", type_name(), get_thread_name_string(buf, buflen));
Thread* current = Thread::current_or_null_safe(); Thread* current = Thread::current_or_null_safe();
assert(current != nullptr, "cannot be called by a detached thread"); assert(current != nullptr, "cannot be called by a detached thread");
st->fill_to(60);
if (!current->is_Java_thread() || JavaThread::cast(current)->is_oop_safe()) { if (!current->is_Java_thread() || JavaThread::cast(current)->is_oop_safe()) {
// Only access threadObj() if current thread is not a JavaThread // Only access threadObj() if current thread is not a JavaThread
// or if it is a JavaThread that can safely access oops. // or if it is a JavaThread that can safely access oops.
oop thread_obj = threadObj(); oop thread_obj = threadObj();
if (thread_obj != nullptr) { if (thread_obj != nullptr) {
if (java_lang_Thread::is_daemon(thread_obj)) st->print(" daemon"); st->print(java_lang_Thread::is_daemon(thread_obj) ? " daemon" : " ");
} }
} }
st->print(" ["); st->print(" [");
@ -1528,8 +1529,9 @@ void JavaThread::print_on_error(outputStream* st, char *buf, int buflen) const {
if (osthread()) { if (osthread()) {
st->print(", id=%d", osthread()->thread_id()); st->print(", id=%d", osthread()->thread_id());
} }
st->print(", stack(" PTR_FORMAT "," PTR_FORMAT ")", st->print(", stack(" PTR_FORMAT "," PTR_FORMAT ") (" PROPERFMT ")",
p2i(stack_end()), p2i(stack_base())); p2i(stack_end()), p2i(stack_base()),
PROPERFMTARGS(stack_size()));
st->print("]"); st->print("]");
ThreadsSMRSupport::print_info_on(this, st); ThreadsSMRSupport::print_info_on(this, st);

View file

@ -483,10 +483,11 @@ void Thread::print_on_error(outputStream* st, char* buf, int buflen) const {
OSThread* os_thr = osthread(); OSThread* os_thr = osthread();
if (os_thr != nullptr) { if (os_thr != nullptr) {
st->fill_to(67);
if (os_thr->get_state() != ZOMBIE) { if (os_thr->get_state() != ZOMBIE) {
st->print(" [stack: " PTR_FORMAT "," PTR_FORMAT "]", st->print(" [id=%d, stack(" PTR_FORMAT "," PTR_FORMAT ") (" PROPERFMT ")]",
p2i(stack_end()), p2i(stack_base())); osthread()->thread_id(), p2i(stack_end()), p2i(stack_base()),
st->print(" [id=%d]", osthread()->thread_id()); PROPERFMTARGS(stack_size()));
} else { } else {
st->print(" terminated"); st->print(" terminated");
} }

View file

@ -1298,14 +1298,19 @@ class PrintOnErrorClosure : public ThreadClosure {
char* _buf; char* _buf;
int _buflen; int _buflen;
bool* _found_current; bool* _found_current;
unsigned _num_printed;
public: public:
PrintOnErrorClosure(outputStream* st, Thread* current, char* buf, PrintOnErrorClosure(outputStream* st, Thread* current, char* buf,
int buflen, bool* found_current) : int buflen, bool* found_current) :
_st(st), _current(current), _buf(buf), _buflen(buflen), _found_current(found_current) {} _st(st), _current(current), _buf(buf), _buflen(buflen), _found_current(found_current),
_num_printed(0) {}
virtual void do_thread(Thread* thread) { virtual void do_thread(Thread* thread) {
_num_printed++;
Threads::print_on_error(thread, _st, _current, _buf, _buflen, _found_current); Threads::print_on_error(thread, _st, _current, _buf, _buflen, _found_current);
} }
unsigned num_printed() const { return _num_printed; }
}; };
// Threads::print_on_error() is called by fatal error handler. It's possible // Threads::print_on_error() is called by fatal error handler. It's possible
@ -1319,12 +1324,18 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf,
bool found_current = false; bool found_current = false;
st->print_cr("Java Threads: ( => current thread )"); st->print_cr("Java Threads: ( => current thread )");
unsigned num_java = 0;
ALL_JAVA_THREADS(thread) { ALL_JAVA_THREADS(thread) {
print_on_error(thread, st, current, buf, buflen, &found_current); print_on_error(thread, st, current, buf, buflen, &found_current);
num_java++;
} }
st->print_cr("Total: %u", num_java);
st->cr(); st->cr();
st->print_cr("Other Threads:"); st->print_cr("Other Threads:");
unsigned num_other = ((VMThread::vm_thread() != nullptr) ? 1 : 0) +
((WatcherThread::watcher_thread() != nullptr) ? 1 : 0) +
((AsyncLogWriter::instance() != nullptr) ? 1 : 0);
print_on_error(VMThread::vm_thread(), st, current, buf, buflen, &found_current); print_on_error(VMThread::vm_thread(), st, current, buf, buflen, &found_current);
print_on_error(WatcherThread::watcher_thread(), st, current, buf, buflen, &found_current); print_on_error(WatcherThread::watcher_thread(), st, current, buf, buflen, &found_current);
print_on_error(AsyncLogWriter::instance(), st, current, buf, buflen, &found_current); print_on_error(AsyncLogWriter::instance(), st, current, buf, buflen, &found_current);
@ -1332,21 +1343,26 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf,
if (Universe::heap() != nullptr) { if (Universe::heap() != nullptr) {
PrintOnErrorClosure print_closure(st, current, buf, buflen, &found_current); PrintOnErrorClosure print_closure(st, current, buf, buflen, &found_current);
Universe::heap()->gc_threads_do(&print_closure); Universe::heap()->gc_threads_do(&print_closure);
num_other += print_closure.num_printed();
} }
if (!found_current) { if (!found_current) {
st->cr(); st->cr();
st->print("=>" PTR_FORMAT " (exited) ", p2i(current)); st->print("=>" PTR_FORMAT " (exited) ", p2i(current));
current->print_on_error(st, buf, buflen); current->print_on_error(st, buf, buflen);
num_other++;
st->cr(); st->cr();
} }
st->print_cr("Total: %u", num_other);
st->cr(); st->cr();
st->print_cr("Threads with active compile tasks:"); st->print_cr("Threads with active compile tasks:");
print_threads_compiling(st, buf, buflen); unsigned num = print_threads_compiling(st, buf, buflen);
st->print_cr("Total: %u", num);
} }
void Threads::print_threads_compiling(outputStream* st, char* buf, int buflen, bool short_form) { unsigned Threads::print_threads_compiling(outputStream* st, char* buf, int buflen, bool short_form) {
unsigned num = 0;
ALL_JAVA_THREADS(thread) { ALL_JAVA_THREADS(thread) {
if (thread->is_Compiler_thread()) { if (thread->is_Compiler_thread()) {
CompilerThread* ct = (CompilerThread*) thread; CompilerThread* ct = (CompilerThread*) thread;
@ -1360,9 +1376,11 @@ void Threads::print_threads_compiling(outputStream* st, char* buf, int buflen, b
thread->print_name_on_error(st, buf, buflen); thread->print_name_on_error(st, buf, buflen);
st->print(" "); st->print(" ");
task->print(st, nullptr, short_form, true); task->print(st, nullptr, short_form, true);
num++;
} }
} }
} }
return num;
} }
void Threads::verify() { void Threads::verify() {

View file

@ -128,7 +128,8 @@ public:
static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen); static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen);
static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf,
int buflen, bool* found_current); int buflen, bool* found_current);
static void print_threads_compiling(outputStream* st, char* buf, int buflen, bool short_form = false); // Print threads busy compiling, and returns the number of printed threads.
static unsigned print_threads_compiling(outputStream* st, char* buf, int buflen, bool short_form = false);
// Get Java threads that are waiting to enter a monitor. // Get Java threads that are waiting to enter a monitor.
static GrowableArray<JavaThread*>* get_pending_threads(ThreadsList * t_list, static GrowableArray<JavaThread*>* get_pending_threads(ThreadsList * t_list,