Skip to content

Commit 178c001

Browse files
committed
8258479: Minor cleanups in VMError
Reviewed-by: lfoltan, coleenp
1 parent c11525a commit 178c001

File tree

8 files changed

+78
-91
lines changed

8 files changed

+78
-91
lines changed

src/hotspot/os/posix/vmError_posix.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2018, 2020 SAP SE. All rights reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -132,7 +133,7 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
132133
VMError::report_and_die(NULL, sig, pc, info, ucVoid);
133134
}
134135

135-
void VMError::reset_signal_handlers() {
136+
void VMError::install_secondary_signal_handler() {
136137
for (int i = 0; i < NUM_SIGNALS; i++) {
137138
save_signal(i, SIGNALS[i]);
138139
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));

src/hotspot/os/windows/vmError_windows.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@ LONG WINAPI crash_handler(struct _EXCEPTION_POINTERS* exceptionInfo) {
4444
return EXCEPTION_CONTINUE_SEARCH;
4545
}
4646

47-
void VMError::reset_signal_handlers() {
47+
void VMError::install_secondary_signal_handler() {
4848
SetUnhandledExceptionFilter(crash_handler);
4949
}
5050

src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ HeapWord* ParallelScavengeHeap::block_start(const void* addr) const {
603603
assert(young_gen()->is_in(addr),
604604
"addr should be in allocated part of young gen");
605605
// called from os::print_location by find or VMError
606-
if (Debugging || VMError::fatal_error_in_progress()) return NULL;
606+
if (Debugging || VMError::is_error_reported()) return NULL;
607607
Unimplemented();
608608
} else if (old_gen()->is_in_reserved(addr)) {
609609
assert(old_gen()->is_in(addr),

src/hotspot/share/runtime/threadSMR.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -540,8 +540,7 @@ void SafeThreadsListPtr::verify_hazard_ptr_scanned() {
540540
return;
541541
}
542542

543-
if (VMError::is_error_reported() &&
544-
VMError::get_first_error_tid() == os::current_thread_id()) {
543+
if (VMError::is_error_reported_in_current_thread()) {
545544
// If there is an error reported by this thread it may use ThreadsList even
546545
// if it's unsafe.
547546
return;

src/hotspot/share/utilities/decoder.cpp

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2017, 2020 SAP SE. All rights reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +26,6 @@
2526
#include "precompiled.hpp"
2627
#include "jvm.h"
2728
#include "memory/allocation.inline.hpp"
28-
#include "runtime/os.hpp"
2929
#include "utilities/decoder.hpp"
3030
#include "utilities/vmError.hpp"
3131

@@ -84,30 +84,25 @@ Mutex* Decoder::shared_decoder_lock() {
8484
}
8585

8686
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
87-
bool error_handling_thread = os::current_thread_id() == VMError::get_first_error_tid();
88-
if (error_handling_thread) {
87+
if (VMError::is_error_reported_in_current_thread()) {
8988
return get_error_handler_instance()->decode(addr, buf, buflen, offset, modulepath, demangle);
9089
} else {
9190
MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);
9291
return get_shared_instance()->decode(addr, buf, buflen, offset, modulepath, demangle);
9392
}
94-
9593
}
9694

9795
bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const void* base) {
98-
bool error_handling_thread = os::current_thread_id() == VMError::get_first_error_tid();
99-
if (error_handling_thread) {
96+
if (VMError::is_error_reported_in_current_thread()) {
10097
return get_error_handler_instance()->decode(addr, buf, buflen, offset, base);
10198
} else {
10299
MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);
103100
return get_shared_instance()->decode(addr, buf, buflen, offset, base);
104101
}
105102
}
106103

107-
108104
bool Decoder::demangle(const char* symbol, char* buf, int buflen) {
109-
bool error_handling_thread = os::current_thread_id() == VMError::get_first_error_tid();
110-
if (error_handling_thread) {
105+
if (VMError::is_error_reported_in_current_thread()) {
111106
return get_error_handler_instance()->demangle(symbol, buf, buflen);
112107
} else {
113108
MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);

src/hotspot/share/utilities/events.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -127,7 +127,7 @@ template <class T> class EventLogBase : public EventLog {
127127
bool should_log() {
128128
// Don't bother adding new entries when we're crashing. This also
129129
// avoids mutating the ring buffer when printing the log.
130-
return !VMError::fatal_error_in_progress();
130+
return !VMError::is_error_reported();
131131
}
132132

133133
// Print the contents of the log

src/hotspot/share/utilities/vmError.cpp

+56-60
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2017, 2020 SAP SE. All rights reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -63,10 +64,25 @@
6364
#include <signal.h>
6465
#endif // PRODUCT
6566

66-
bool VMError::_error_reported = false;
67-
68-
// call this when the VM is dying--it might loosen some asserts
69-
bool VMError::is_error_reported() { return _error_reported; }
67+
bool VMError::coredump_status;
68+
char VMError::coredump_message[O_BUFLEN];
69+
int VMError::_current_step;
70+
const char* VMError::_current_step_info;
71+
volatile jlong VMError::_reporting_start_time = -1;
72+
volatile bool VMError::_reporting_did_timeout = false;
73+
volatile jlong VMError::_step_start_time = -1;
74+
volatile bool VMError::_step_did_timeout = false;
75+
volatile intptr_t VMError::_first_error_tid = -1;
76+
int VMError::_id;
77+
const char* VMError::_message;
78+
char VMError::_detail_msg[1024];
79+
Thread* VMError::_thread;
80+
address VMError::_pc;
81+
void* VMError::_siginfo;
82+
void* VMError::_context;
83+
const char* VMError::_filename;
84+
int VMError::_lineno;
85+
size_t VMError::_size;
7086

7187
// returns an address which is guaranteed to generate a SIGSEGV on read,
7288
// for test purposes, which is not NULL and contains bits in every word
@@ -80,7 +96,7 @@ void* VMError::get_segfault_address() {
8096
}
8197

8298
// List of environment variables that should be reported in error log file.
83-
const char *env_list[] = {
99+
static const char* env_list[] = {
84100
// All platforms
85101
"JAVA_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH",
86102
"PATH", "USERNAME",
@@ -151,9 +167,6 @@ static void print_bug_submit_message(outputStream *out, Thread *thread) {
151167
out->print_raw_cr("#");
152168
}
153169

154-
bool VMError::coredump_status;
155-
char VMError::coredump_message[O_BUFLEN];
156-
157170
void VMError::record_coredump_status(const char* message, bool status) {
158171
coredump_status = status;
159172
strncpy(coredump_message, message, sizeof(coredump_message));
@@ -358,40 +371,15 @@ static void report_vm_version(outputStream* st, char* buf, int buflen) {
358371
);
359372
}
360373

361-
// This is the main function to report a fatal error. Only one thread can
362-
// call this function, so we don't need to worry about MT-safety. But it's
363-
// possible that the error handler itself may crash or die on an internal
364-
// error, for example, when the stack/heap is badly damaged. We must be
365-
// able to handle recursive errors that happen inside error handler.
366-
//
367-
// Error reporting is done in several steps. If a crash or internal error
368-
// occurred when reporting an error, the nested signal/exception handler
369-
// can skip steps that are already (or partially) done. Error reporting will
370-
// continue from the next step. This allows us to retrieve and print
371-
// information that may be unsafe to get after a fatal error. If it happens,
372-
// you may find nested report_and_die() frames when you look at the stack
373-
// in a debugger.
374-
//
375-
// In general, a hang in error handler is much worse than a crash or internal
376-
// error, as it's harder to recover from a hang. Deadlock can happen if we
377-
// try to grab a lock that is already owned by current thread, or if the
378-
// owner is blocked forever (e.g. in os::infinite_sleep()). If possible, the
379-
// error handler and all the functions it called should avoid grabbing any
380-
// lock. An important thing to notice is that memory allocation needs a lock.
381-
//
382-
// We should avoid using large stack allocated buffers. Many errors happen
383-
// when stack space is already low. Making things even worse is that there
384-
// could be nested report_and_die() calls on stack (see above). Only one
385-
// thread can report error, so large buffers are statically allocated in data
386-
// segment.
387-
388-
int VMError::_current_step;
389-
const char* VMError::_current_step_info;
374+
// Returns true if at least one thread reported a fatal error and fatal error handling is in process.
375+
bool VMError::is_error_reported() {
376+
return _first_error_tid != -1;
377+
}
390378

391-
volatile jlong VMError::_reporting_start_time = -1;
392-
volatile bool VMError::_reporting_did_timeout = false;
393-
volatile jlong VMError::_step_start_time = -1;
394-
volatile bool VMError::_step_did_timeout = false;
379+
// Returns true if the current thread reported a fatal error.
380+
bool VMError::is_error_reported_in_current_thread() {
381+
return _first_error_tid == os::current_thread_id();
382+
}
395383

396384
// Helper, return current timestamp for timeout handling.
397385
jlong VMError::get_current_timestamp() {
@@ -422,6 +410,32 @@ void VMError::clear_step_start_time() {
422410
return Atomic::store(&_step_start_time, (jlong)0);
423411
}
424412

413+
// This is the main function to report a fatal error. Only one thread can
414+
// call this function, so we don't need to worry about MT-safety. But it's
415+
// possible that the error handler itself may crash or die on an internal
416+
// error, for example, when the stack/heap is badly damaged. We must be
417+
// able to handle recursive errors that happen inside error handler.
418+
//
419+
// Error reporting is done in several steps. If a crash or internal error
420+
// occurred when reporting an error, the nested signal/exception handler
421+
// can skip steps that are already (or partially) done. Error reporting will
422+
// continue from the next step. This allows us to retrieve and print
423+
// information that may be unsafe to get after a fatal error. If it happens,
424+
// you may find nested report_and_die() frames when you look at the stack
425+
// in a debugger.
426+
//
427+
// In general, a hang in error handler is much worse than a crash or internal
428+
// error, as it's harder to recover from a hang. Deadlock can happen if we
429+
// try to grab a lock that is already owned by current thread, or if the
430+
// owner is blocked forever (e.g. in os::infinite_sleep()). If possible, the
431+
// error handler and all the functions it called should avoid grabbing any
432+
// lock. An important thing to notice is that memory allocation needs a lock.
433+
//
434+
// We should avoid using large stack allocated buffers. Many errors happen
435+
// when stack space is already low. Making things even worse is that there
436+
// could be nested report_and_die() calls on stack (see above). Only one
437+
// thread can report error, so large buffers are statically allocated in data
438+
// segment.
425439
void VMError::report(outputStream* st, bool _verbose) {
426440

427441
# define BEGIN if (_current_step == 0) { _current_step = __LINE__;
@@ -654,7 +668,6 @@ void VMError::report(outputStream* st, bool _verbose) {
654668
os::print_summary_info(st, buf, sizeof(buf));
655669
}
656670

657-
658671
STEP("printing date and time")
659672

660673
if (_verbose) {
@@ -695,7 +708,6 @@ void VMError::report(outputStream* st, bool _verbose) {
695708
}
696709
}
697710

698-
699711
STEP("printing stack bounds")
700712

701713
if (_verbose) {
@@ -1240,8 +1252,6 @@ void VMError::print_vm_info(outputStream* st) {
12401252
st->print_cr("END.");
12411253
}
12421254

1243-
volatile intptr_t VMError::_first_error_tid = -1;
1244-
12451255
/** Expand a pattern into a buffer starting at pos and open a file using constructed path */
12461256
static int expand_and_open(const char* pattern, bool overwrite_existing, char* buf, size_t buflen, size_t pos) {
12471257
int fd = -1;
@@ -1298,17 +1308,6 @@ static int prepare_log_file(const char* pattern, const char* default_pattern, bo
12981308
return fd;
12991309
}
13001310

1301-
int VMError::_id;
1302-
const char* VMError::_message;
1303-
char VMError::_detail_msg[1024];
1304-
Thread* VMError::_thread;
1305-
address VMError::_pc;
1306-
void* VMError::_siginfo;
1307-
void* VMError::_context;
1308-
const char* VMError::_filename;
1309-
int VMError::_lineno;
1310-
size_t VMError::_size;
1311-
13121311
void VMError::report_and_die(Thread* thread, unsigned int sig, address pc, void* siginfo,
13131312
void* context, const char* detail_fmt, ...)
13141313
{
@@ -1395,9 +1394,6 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
13951394
_size = size;
13961395
jio_vsnprintf(_detail_msg, sizeof(_detail_msg), detail_fmt, detail_args);
13971396

1398-
// first time
1399-
_error_reported = true;
1400-
14011397
reporting_started();
14021398
if (!TestUnresponsiveErrorHandler) {
14031399
// Record reporting_start_time unless we're running the
@@ -1420,7 +1416,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
14201416

14211417
// reset signal handlers or exception filter; make sure recursive crashes
14221418
// are handled properly.
1423-
reset_signal_handlers();
1419+
install_secondary_signal_handler();
14241420
} else {
14251421
#if defined(_WINDOWS)
14261422
// If UseOSErrorReporting we call this for each level of the call stack

src/hotspot/share/utilities/vmError.hpp

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2017, 2020 SAP SE. All rights reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -84,13 +85,9 @@ class VMError : public AllStatic {
8485
// Whether or not the last error reporting step did timeout.
8586
static volatile bool _step_did_timeout;
8687

87-
static bool _error_reported;
88-
89-
public:
90-
91-
// set signal handlers on Solaris/Linux or the default exception filter
92-
// on Windows, to handle recursive crashes.
93-
static void reset_signal_handlers();
88+
// Install secondary signal handler to handle secondary faults during error reporting
89+
// (see VMError::crash_handler)
90+
static void install_secondary_signal_handler();
9491

9592
// handle -XX:+ShowMessageBoxOnError. buf is used to format the message string
9693
static void show_message_box(char* buf, int buflen);
@@ -171,18 +168,17 @@ class VMError : public AllStatic {
171168
// signal was not changed by error reporter
172169
static address get_resetted_sighandler(int sig);
173170

174-
// check to see if fatal error reporting is in progress
175-
static bool fatal_error_in_progress() { return _first_error_tid != -1; }
176-
177-
static intptr_t get_first_error_tid() { return _first_error_tid; }
178-
179171
// Called by the WatcherThread to check if error reporting has timed-out.
180172
// Returns true if error reporting has not completed within the ErrorLogTimeout limit.
181173
static bool check_timeout();
182174

183-
// Support for avoiding multiple asserts
175+
// Returns true if at least one thread reported a fatal error and
176+
// fatal error handling is in process.
184177
static bool is_error_reported();
185178

179+
// Returns true if the current thread reported a fatal error.
180+
static bool is_error_reported_in_current_thread();
181+
186182
DEBUG_ONLY(static void controlled_crash(int how);)
187183

188184
// returns an address which is guaranteed to generate a SIGSEGV on read,

0 commit comments

Comments
 (0)