vmError_posix.cpp revision 11658:8a5735c11a84
1/*
2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "memory/filemap.hpp"
27#include "runtime/arguments.hpp"
28#include "runtime/os.hpp"
29#include "runtime/thread.hpp"
30#include "utilities/vmError.hpp"
31
32#include <sys/types.h>
33#include <sys/wait.h>
34#include <signal.h>
35
36#ifdef LINUX
37#include <sys/syscall.h>
38#include <unistd.h>
39#endif
40#ifdef SOLARIS
41#include <thread.h>
42#endif
43#ifdef AIX
44#include <unistd.h>
45#endif
46#ifdef BSD
47#include <sys/syscall.h>
48#include <unistd.h>
49#endif
50
51
52// handle all synchronous program error signals which may happen during error
53// reporting. They must be unblocked, caught, handled.
54
55static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
56static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
57
58// Space for our "saved" signal flags and handlers
59static int resettedSigflags[NUM_SIGNALS];
60static address resettedSighandler[NUM_SIGNALS];
61
62static void save_signal(int idx, int sig)
63{
64  struct sigaction sa;
65  sigaction(sig, NULL, &sa);
66  resettedSigflags[idx]   = sa.sa_flags;
67  resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
68                              ? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
69                              : CAST_FROM_FN_PTR(address, sa.sa_handler);
70}
71
72int VMError::get_resetted_sigflags(int sig) {
73  for (int i = 0; i < NUM_SIGNALS; i++) {
74    if (SIGNALS[i] == sig) {
75      return resettedSigflags[i];
76    }
77  }
78  return -1;
79}
80
81address VMError::get_resetted_sighandler(int sig) {
82  for (int i = 0; i < NUM_SIGNALS; i++) {
83    if (SIGNALS[i] == sig) {
84      return resettedSighandler[i];
85    }
86  }
87  return NULL;
88}
89
90static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
91  // unmask current signal
92  sigset_t newset;
93  sigemptyset(&newset);
94  sigaddset(&newset, sig);
95  // also unmask other synchronous signals
96  for (int i = 0; i < NUM_SIGNALS; i++) {
97    sigaddset(&newset, SIGNALS[i]);
98  }
99  os::Posix::unblock_thread_signal_mask(&newset);
100
101  // support safefetch faults in error handling
102  ucontext_t* const uc = (ucontext_t*) ucVoid;
103  address const pc = uc ? os::Posix::ucontext_get_pc(uc) : NULL;
104
105  if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
106    os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
107    return;
108  }
109
110  VMError::report_and_die(NULL, sig, pc, info, ucVoid);
111}
112
113void VMError::reset_signal_handlers() {
114  // install signal handlers for all synchronous program error signals
115  sigset_t newset;
116  sigemptyset(&newset);
117
118  for (int i = 0; i < NUM_SIGNALS; i++) {
119    save_signal(i, SIGNALS[i]);
120    os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
121    sigaddset(&newset, SIGNALS[i]);
122  }
123  os::Posix::unblock_thread_signal_mask(&newset);
124
125}
126
127// Write a hint to the stream in case siginfo relates to a segv/bus error
128// and the offending address points into CDS archive.
129void VMError::check_failing_cds_access(outputStream* st, const void* siginfo) {
130  if (siginfo && UseSharedSpaces) {
131    const siginfo_t* const si = (siginfo_t*)siginfo;
132    if (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) {
133      const void* const fault_addr = si->si_addr;
134      if (fault_addr != NULL) {
135        FileMapInfo* const mapinfo = FileMapInfo::current_info();
136        if (mapinfo->is_in_shared_space(fault_addr)) {
137          st->print("Error accessing class data sharing archive. "
138            "Mapped file inaccessible during execution, possible disk/network problem.");
139        }
140      }
141    }
142  }
143}
144
145