This commit is contained in:
Coleen Phillimore 2015-11-26 00:00:25 +00:00
commit f3c2ec63b4
14 changed files with 202 additions and 480 deletions

View File

@ -3785,7 +3785,7 @@ os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& me
void os::print_statistics() {
}
int os::message_box(const char* title, const char* message) {
bool os::message_box(const char* title, const char* message) {
int i;
fdStream err(defaultStream::error_fd());
for (i = 0; i < 78; i++) err.print_raw("=");
@ -4914,3 +4914,28 @@ void TestReserveMemorySpecial_test() {
// No tests available for this platform
}
#endif
bool os::start_debugging(char *buf, int buflen) {
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen -len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'dbx -a %d'; then switch to thread tid " INTX_FORMAT ", k-tid " INTX_FORMAT "\n"
"Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(),
os::current_thread_id(), thread_self());
bool yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, buflen, "dbx -a %d", os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
return yes;
}

View File

@ -1,134 +0,0 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "utilities/vmError.hpp"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'dbx -a %d'; then switch to thread tid " INTX_FORMAT ", k-tid " INTX_FORMAT "\n"
"Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(),
os::current_thread_id(), thread_self());
yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, buflen, "dbx -a %d", os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
} while (yes);
}
// Handle all synchronous signals which may happen during signal handling,
// not just SIGSEGV and SIGBUS.
static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
// Space for our "saved" signal flags and handlers
static int resettedSigflags[NUM_SIGNALS];
static address resettedSighandler[NUM_SIGNALS];
static void save_signal(int idx, int sig) {
struct sigaction sa;
sigaction(sig, NULL, &sa);
resettedSigflags[idx] = sa.sa_flags;
resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
: CAST_FROM_FN_PTR(address, sa.sa_handler);
}
int VMError::get_resetted_sigflags(int sig) {
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSigflags[i];
}
}
return -1;
}
address VMError::get_resetted_sighandler(int sig) {
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSighandler[i];
}
}
return NULL;
}
static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
// Unmask current signal.
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
// and all other synchronous signals too.
for (int i = 0; i < NUM_SIGNALS; i++) {
sigaddset(&newset, SIGNALS[i]);
}
sigthreadmask(SIG_UNBLOCK, &newset, NULL);
// support safefetch faults in error handling
ucontext_t* const uc = (ucontext_t*) ucVoid;
address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL;
if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return;
}
VMError::report_and_die(NULL, sig, pc, info, ucVoid);
}
void VMError::reset_signal_handlers() {
sigset_t newset;
sigemptyset(&newset);
for (int i = 0; i < NUM_SIGNALS; i++) {
save_signal(i, SIGNALS[i]);
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
sigaddset(&newset, SIGNALS[i]);
}
sigthreadmask(SIG_UNBLOCK, &newset, NULL);
}

View File

@ -3768,7 +3768,7 @@ void os::os_exception_wrapper(java_call_t f, JavaValue* value,
void os::print_statistics() {
}
int os::message_box(const char* title, const char* message) {
bool os::message_box(const char* title, const char* message) {
int i;
fdStream err(defaultStream::error_fd());
for (i = 0; i < 78; i++) err.print_raw("=");
@ -4672,3 +4672,29 @@ void TestReserveMemorySpecial_test() {
// No tests available for this platform
}
#endif
bool os::start_debugging(char *buf, int buflen) {
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen-len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(),
os::current_thread_id(), os::current_thread_id());
bool yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, sizeof(buf), "gdb /proc/%d/exe %d",
os::current_process_id(), os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
return yes;
}

View File

@ -1,138 +0,0 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "utilities/vmError.hpp"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <signal.h>
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(),
os::current_thread_id(), os::current_thread_id());
yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, buflen, "gdb /proc/%d/exe %d",
os::current_process_id(), os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
} while (yes);
}
// handle all synchronous program error signals which may happen during error
// reporting. They must be unblocked, caught, handled.
static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
// Space for our "saved" signal flags and handlers
static int resettedSigflags[NUM_SIGNALS];
static address resettedSighandler[NUM_SIGNALS];
static void save_signal(int idx, int sig)
{
struct sigaction sa;
sigaction(sig, NULL, &sa);
resettedSigflags[idx] = sa.sa_flags;
resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
: CAST_FROM_FN_PTR(address, sa.sa_handler);
}
int VMError::get_resetted_sigflags(int sig) {
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSigflags[i];
}
}
return -1;
}
address VMError::get_resetted_sighandler(int sig) {
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSighandler[i];
}
}
return NULL;
}
static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
// also unmask other synchronous signals
for (int i = 0; i < NUM_SIGNALS; i++) {
sigaddset(&newset, SIGNALS[i]);
}
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
// support safefetch faults in error handling
ucontext_t* const uc = (ucontext_t*) ucVoid;
address const pc = uc ? os::Bsd::ucontext_get_pc(uc) : NULL;
if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
os::Bsd::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return;
}
VMError::report_and_die(NULL, sig, pc, info, ucVoid);
}
void VMError::reset_signal_handlers() {
// install signal handlers for all synchronous program error signals
sigset_t newset;
sigemptyset(&newset);
for (int i = 0; i < NUM_SIGNALS; i++) {
save_signal(i, SIGNALS[i]);
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
sigaddset(&newset, SIGNALS[i]);
}
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
}

View File

@ -4970,7 +4970,7 @@ os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& me
void os::print_statistics() {
}
int os::message_box(const char* title, const char* message) {
bool os::message_box(const char* title, const char* message) {
int i;
fdStream err(defaultStream::error_fd());
for (i = 0; i < 78; i++) err.print_raw("=");
@ -5995,6 +5995,34 @@ int os::get_core_path(char* buffer, size_t bufferSize) {
return strlen(buffer);
}
bool os::start_debugging(char *buf, int buflen) {
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen-len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " UINTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(),
os::current_thread_id(), os::current_thread_id());
bool yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, sizeof(buf), "gdb /proc/%d/exe %d",
os::current_process_id(), os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
return yes;
}
/////////////// Unit tests ///////////////
#ifndef PRODUCT

View File

@ -1,139 +0,0 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "utilities/vmError.hpp"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <signal.h>
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " UINTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(),
os::current_thread_id(), os::current_thread_id());
yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, buflen, "gdb /proc/%d/exe %d",
os::current_process_id(), os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
} while (yes);
}
// handle all synchronous program error signals which may happen during error
// reporting. They must be unblocked, caught, handled.
static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
// Space for our "saved" signal flags and handlers
static int resettedSigflags[NUM_SIGNALS];
static address resettedSighandler[NUM_SIGNALS];
static void save_signal(int idx, int sig)
{
struct sigaction sa;
sigaction(sig, NULL, &sa);
resettedSigflags[idx] = sa.sa_flags;
resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
: CAST_FROM_FN_PTR(address, sa.sa_handler);
}
int VMError::get_resetted_sigflags(int sig) {
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSigflags[i];
}
}
return -1;
}
address VMError::get_resetted_sighandler(int sig) {
for (int i = 0; i < NUM_SIGNALS; i++) {
if (SIGNALS[i] == sig) {
return resettedSighandler[i];
}
}
return NULL;
}
static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
// also unmask other synchronous signals
for (int i = 0; i < NUM_SIGNALS; i++) {
sigaddset(&newset, SIGNALS[i]);
}
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
// support safefetch faults in error handling
ucontext_t* const uc = (ucontext_t*) ucVoid;
address const pc = uc ? os::Linux::ucontext_get_pc(uc) : NULL;
if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return;
}
VMError::report_and_die(NULL, sig, pc, info, ucVoid);
}
void VMError::reset_signal_handlers() {
// install signal handlers for all synchronous program error signals
sigset_t newset;
sigemptyset(&newset);
for (int i = 0; i < NUM_SIGNALS; i++) {
save_signal(i, SIGNALS[i]);
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
sigaddset(&newset, SIGNALS[i]);
}
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
}

View File

@ -988,6 +988,39 @@ void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) {
}
}
int os::Posix::unblock_thread_signal_mask(const sigset_t *set) {
return pthread_sigmask(SIG_UNBLOCK, set, NULL);
}
address os::Posix::ucontext_get_pc(ucontext_t* ctx) {
#ifdef TARGET_OS_FAMILY_linux
return Linux::ucontext_get_pc(ctx);
#elif defined(TARGET_OS_FAMILY_solaris)
return Solaris::ucontext_get_pc(ctx);
#elif defined(TARGET_OS_FAMILY_aix)
return Aix::ucontext_get_pc(ctx);
#elif defined(TARGET_OS_FAMILY_bsd)
return Bsd::ucontext_get_pc(ctx);
#else
VMError::report_and_die("unimplemented ucontext_get_pc");
#endif
}
void os::Posix::ucontext_set_pc(ucontext_t* ctx, address pc) {
#ifdef TARGET_OS_FAMILY_linux
Linux::ucontext_set_pc(ctx, pc);
#elif defined(TARGET_OS_FAMILY_solaris)
Solaris::ucontext_set_pc(ctx, pc);
#elif defined(TARGET_OS_FAMILY_aix)
Aix::ucontext_set_pc(ctx, pc);
#elif defined(TARGET_OS_FAMILY_bsd)
Bsd::ucontext_set_pc(ctx, pc);
#else
VMError::report_and_die("unimplemented ucontext_get_pc");
#endif
}
os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
}

View File

@ -57,6 +57,9 @@ public:
// Prints a short one-line description of a signal set.
static void print_signal_set_short(outputStream* st, const sigset_t* set);
// unblocks the signal masks for current thread
static int unblock_thread_signal_mask(const sigset_t *set);
// Writes a one-line description of a combination of sigaction.sa_flags
// into a user provided buffer. Returns that buffer.
static const char* describe_sa_flags(int flags, char* buffer, size_t size);
@ -67,6 +70,9 @@ public:
// A POSIX conform, platform-independend siginfo print routine.
static void print_siginfo_brief(outputStream* os, const siginfo_t* si);
static address ucontext_get_pc(ucontext_t* ctx);
// Set PC into context. Needed for continuation after signal.
static void ucontext_set_pc(ucontext_t* ctx, address pc);
};
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,35 +30,23 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <thread.h>
#include <signal.h>
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
int len = (int)strlen(buf);
char *p = &buf[len];
#ifdef TARGET_OS_FAMILY_linux
#include <sys/syscall.h>
#include <unistd.h>
#endif
#ifdef TARGET_OS_FAMILY_solaris
#include <thread.h>
#endif
#ifdef TARGET_OS_FAMILY_aix
#include <unistd.h>
#endif
#ifdef TARGET_OS_FAMILY_bsd
#include <sys/syscall.h>
#include <unistd.h>
#endif
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'dbx - %d'; then switch to thread " INTX_FORMAT "\n"
"Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_thread_id());
yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, buflen, "dbx - %d", os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
} while (yes);
}
// handle all synchronous program error signals which may happen during error
// reporting. They must be unblocked, caught, handled.
@ -107,13 +95,14 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
for (int i = 0; i < NUM_SIGNALS; i++) {
sigaddset(&newset, SIGNALS[i]);
}
thr_sigsetmask(SIG_UNBLOCK, &newset, NULL);
os::Posix::unblock_thread_signal_mask(&newset);
// support safefetch faults in error handling
ucontext_t* const uc = (ucontext_t*) ucVoid;
address const pc = uc ? os::Solaris::ucontext_get_pc(uc) : NULL;
address const pc = uc ? os::Posix::ucontext_get_pc(uc) : NULL;
if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return;
}
@ -130,5 +119,6 @@ void VMError::reset_signal_handlers() {
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
sigaddset(&newset, SIGNALS[i]);
}
thr_sigsetmask(SIG_UNBLOCK, &newset, NULL);
os::Posix::unblock_thread_signal_mask(&newset);
}

View File

@ -3611,7 +3611,7 @@ void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
void os::print_statistics() {
}
int os::message_box(const char* title, const char* message) {
bool os::message_box(const char* title, const char* message) {
int i;
fdStream err(defaultStream::error_fd());
for (i = 0; i < 78; i++) err.print_raw("=");
@ -5804,3 +5804,27 @@ void TestReserveMemorySpecial_test() {
// No tests available for this platform
}
#endif
bool os::start_debugging(char *buf, int buflen) {
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen-len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, run 'dbx - %d'; then switch to thread " INTX_FORMAT "\n"
"Enter 'yes' to launch dbx automatically (PATH must include dbx)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_thread_id());
bool yes = os::message_box("Unexpected Error", buf);
if (yes) {
// yes, user asked VM to launch debugger
jio_snprintf(buf, sizeof(buf), "dbx - %d", os::current_process_id());
os::fork_and_exec(buf);
yes = false;
}
return yes;
}

View File

@ -4005,7 +4005,7 @@ void os::wait_for_keypress_at_exit(void) {
}
int os::message_box(const char* title, const char* message) {
bool os::message_box(const char* title, const char* message) {
int result = MessageBox(NULL, message, title,
MB_YESNO | MB_ICONERROR | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);
return result == IDYES;
@ -5513,7 +5513,31 @@ void os::Kernel32Dll::initializeCommon() {
}
}
bool os::start_debugging(char *buf, int buflen) {
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen-len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, attach Visual Studio to process %d; then switch to thread 0x%x\n"
"Select 'Yes' to launch Visual Studio automatically (PATH must include msdev)\n"
"Otherwise, select 'No' to abort...",
os::current_process_id(), os::current_thread_id());
bool yes = os::message_box("Unexpected Error", buf);
if (yes) {
// os::breakpoint() calls DebugBreak(), which causes a breakpoint
// exception. If VM is running inside a debugger, the debugger will
// catch the exception. Otherwise, the breakpoint exception will reach
// the default windows exception handler, which can spawn a debugger and
// automatically attach to the dying VM.
os::breakpoint();
yes = false;
}
return yes;
}
#ifndef JDK6_OR_EARLIER

View File

@ -28,38 +28,6 @@
#include "runtime/thread.hpp"
#include "utilities/vmError.hpp"
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
int len = (int)strlen(buf);
char *p = &buf[len];
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
"To debug, attach Visual Studio to process %d; then switch to thread 0x%x\n"
"Select 'Yes' to launch Visual Studio automatically (PATH must include msdev)\n"
"Otherwise, select 'No' to abort...",
os::current_process_id(), os::current_thread_id());
yes = os::message_box("Unexpected Error", buf) != 0;
if (yes) {
// yes, user asked VM to launch debugger
//
// os::breakpoint() calls DebugBreak(), which causes a breakpoint
// exception. If VM is running inside a debugger, the debugger will
// catch the exception. Otherwise, the breakpoint exception will reach
// the default windows exception handler, which can spawn a debugger and
// automatically attach to the dying VM.
os::breakpoint();
yes = false;
}
} while (yes);
}
int VMError::get_resetted_sigflags(int sig) {
return -1;
}

View File

@ -476,6 +476,7 @@ class os: AllStatic {
static ExtendedPC get_thread_pc(Thread *thread);
static void breakpoint();
static bool start_debugging(char *buf, int buflen);
static address current_stack_pointer();
static address current_stack_base();
@ -483,7 +484,7 @@ class os: AllStatic {
static void verify_stack_alignment() PRODUCT_RETURN;
static int message_box(const char* title, const char* message);
static bool message_box(const char* title, const char* message);
static char* do_you_want_to_debug(const char* message);
// run cmd in a separate process and return its exit code; or -1 on failures

View File

@ -1349,3 +1349,11 @@ void VMError::report_java_out_of_memory(const char* message) {
VMThread::execute(&op);
}
}
void VMError::show_message_box(char *buf, int buflen) {
bool yes;
do {
error_string(buf, buflen);
yes = os::start_debugging(buf,buflen);
} while (yes);
}