8252324: Signal related code should be shared among POSIX platforms

Reviewed-by: coleenp, dholmes, stuefe, ysuenaga
This commit is contained in:
Gerard Ziemski 2020-10-07 16:21:51 +00:00
parent 1e8e543b26
commit 4fe07ccc53
21 changed files with 1826 additions and 3622 deletions

File diff suppressed because it is too large Load Diff

@ -34,12 +34,6 @@ static bool zero_page_read_protected() { return false; }
class Aix {
friend class os;
static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
// __sigaction(), signal() is loaded
static struct sigaction *(*get_signal_action)(int);
static void check_signal_handler(int sig);
private:
static julong _physical_memory;
@ -89,7 +83,6 @@ class Aix {
public:
static void init_thread_fpu_state();
static pthread_t main_thread(void) { return _main_thread; }
static void hotspot_sigmask(Thread* thread);
// Given an address, returns the size of the page backing that address
static size_t query_pagesize(void* p);
@ -107,23 +100,6 @@ class Aix {
static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_aix_signal, harmlessly.
static bool signal_handlers_are_installed;
static int get_our_sigflags(int);
static void set_our_sigflags(int, int);
static void signal_sets_init();
static void install_signal_handlers();
static void set_signal_handler(int, bool);
static sigset_t* unblocked_signals();
static sigset_t* vm_signals();
// For signal-chaining
static struct sigaction *get_chained_signal_action(int sig);
static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
// libpthread version string
static void libpthread_init();
@ -204,7 +180,6 @@ class Aix {
// (on AIX, using libperfstat, on PASE with libo4.so).
// Returns true if ok, false if error.
static bool get_meminfo(meminfo_t* pmi);
};
#endif // OS_AIX_OS_AIX_HPP

File diff suppressed because it is too large Load Diff

@ -33,13 +33,6 @@ static bool zero_page_read_protected() { return true; }
class Bsd {
friend class os;
// For signal-chaining
static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
// __sigaction(), signal() is loaded
static struct sigaction *(*get_signal_action)(int);
static void check_signal_handler(int sig);
#ifdef __APPLE__
// mach_absolute_time
static mach_timebase_info_data_t _timebase_info;
@ -70,8 +63,6 @@ class Bsd {
static void init_thread_fpu_state();
static pthread_t main_thread(void) { return _main_thread; }
static void hotspot_sigmask(Thread* thread);
static pid_t gettid();
static int page_size(void) { return _page_size; }
@ -84,23 +75,6 @@ class Bsd {
static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_bsd_signal, harmlessly.
static bool signal_handlers_are_installed;
static int get_our_sigflags(int);
static void set_our_sigflags(int, int);
static void signal_sets_init();
static void install_signal_handlers();
static void set_signal_handler(int, bool);
static sigset_t* unblocked_signals();
static sigset_t* vm_signals();
// For signal-chaining
static struct sigaction *get_chained_signal_action(int sig);
static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
// Real-time clock functions
static void clock_init(void);

File diff suppressed because it is too large Load Diff

@ -36,12 +36,6 @@ class Linux {
friend class OSContainer;
friend class TestReserveMemorySpecial;
static bool libjsig_is_loaded; // libjsig that interposes sigaction(),
// __sigaction(), signal() is loaded
static struct sigaction *(*get_signal_action)(int);
static void check_signal_handler(int sig);
static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
static int (*_pthread_setname_np)(pthread_t, const char*);
@ -133,7 +127,6 @@ class Linux {
// returns kernel thread id (similar to LWP id on Solaris), which can be
// used to access /proc
static pid_t gettid();
static void hotspot_sigmask(Thread* thread);
static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }
static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }
@ -148,23 +141,6 @@ class Linux {
static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_linux_signal, harmlessly.
static bool signal_handlers_are_installed;
static int get_our_sigflags(int);
static void set_our_sigflags(int, int);
static void signal_sets_init();
static void install_signal_handlers();
static void set_signal_handler(int, bool);
static sigset_t* unblocked_signals();
static sigset_t* vm_signals();
// For signal-chaining
static struct sigaction *get_chained_signal_action(int sig);
static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
// GNU libc and libpthread version strings
static const char *glibc_version() { return _glibc_version; }
static const char *libpthread_version() { return _libpthread_version; }

@ -26,6 +26,7 @@
#include "jvm.h"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/osThread.hpp"
#include "signals_posix.hpp"
#include <signal.h>
@ -78,7 +79,7 @@ JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler))
case SHUTDOWN2_SIGNAL:
case SHUTDOWN3_SIGNAL:
if (ReduceSignalUsage) return (void*)-1;
if (os::Posix::is_sig_ignored(sig)) return (void*)1;
if (PosixSignals::is_sig_ignored(sig)) return (void*)1;
}
void* oldHandler = os::signal(sig, newHandler);
@ -102,7 +103,7 @@ JVM_ENTRY_NO_ENV(jboolean, JVM_RaiseSignal(jint sig))
}
}
else if ((sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL ||
sig == SHUTDOWN3_SIGNAL) && os::Posix::is_sig_ignored(sig)) {
sig == SHUTDOWN3_SIGNAL) && PosixSignals::is_sig_ignored(sig)) {
// do not allow SHUTDOWN1_SIGNAL to be raised when SHUTDOWN1_SIGNAL
// is ignored, since no handler for them is actually registered in JVM
// or via JVM_RegisterSignal.

@ -53,13 +53,6 @@
#include <unistd.h>
#include <utmpx.h>
// Todo: provide a os::get_max_process_id() or similar. Number of processes
// may have been configured, can be read more accurately from proc fs etc.
#ifndef MAX_PID
#define MAX_PID INT_MAX
#endif
#define IS_VALID_PID(p) (p > 0 && p < MAX_PID)
#define ROOT_UID 0
#ifndef MAP_ANONYMOUS
@ -705,603 +698,6 @@ void os::naked_short_sleep(jlong ms) {
return;
}
static const struct {
int sig; const char* name;
}
g_signal_info[] =
{
{ SIGABRT, "SIGABRT" },
#ifdef SIGAIO
{ SIGAIO, "SIGAIO" },
#endif
{ SIGALRM, "SIGALRM" },
#ifdef SIGALRM1
{ SIGALRM1, "SIGALRM1" },
#endif
{ SIGBUS, "SIGBUS" },
#ifdef SIGCANCEL
{ SIGCANCEL, "SIGCANCEL" },
#endif
{ SIGCHLD, "SIGCHLD" },
#ifdef SIGCLD
{ SIGCLD, "SIGCLD" },
#endif
{ SIGCONT, "SIGCONT" },
#ifdef SIGCPUFAIL
{ SIGCPUFAIL, "SIGCPUFAIL" },
#endif
#ifdef SIGDANGER
{ SIGDANGER, "SIGDANGER" },
#endif
#ifdef SIGDIL
{ SIGDIL, "SIGDIL" },
#endif
#ifdef SIGEMT
{ SIGEMT, "SIGEMT" },
#endif
{ SIGFPE, "SIGFPE" },
#ifdef SIGFREEZE
{ SIGFREEZE, "SIGFREEZE" },
#endif
#ifdef SIGGFAULT
{ SIGGFAULT, "SIGGFAULT" },
#endif
#ifdef SIGGRANT
{ SIGGRANT, "SIGGRANT" },
#endif
{ SIGHUP, "SIGHUP" },
{ SIGILL, "SIGILL" },
#ifdef SIGINFO
{ SIGINFO, "SIGINFO" },
#endif
{ SIGINT, "SIGINT" },
#ifdef SIGIO
{ SIGIO, "SIGIO" },
#endif
#ifdef SIGIOINT
{ SIGIOINT, "SIGIOINT" },
#endif
#ifdef SIGIOT
// SIGIOT is there for BSD compatibility, but on most Unices just a
// synonym for SIGABRT. The result should be "SIGABRT", not
// "SIGIOT".
#if (SIGIOT != SIGABRT )
{ SIGIOT, "SIGIOT" },
#endif
#endif
#ifdef SIGKAP
{ SIGKAP, "SIGKAP" },
#endif
{ SIGKILL, "SIGKILL" },
#ifdef SIGLOST
{ SIGLOST, "SIGLOST" },
#endif
#ifdef SIGLWP
{ SIGLWP, "SIGLWP" },
#endif
#ifdef SIGLWPTIMER
{ SIGLWPTIMER, "SIGLWPTIMER" },
#endif
#ifdef SIGMIGRATE
{ SIGMIGRATE, "SIGMIGRATE" },
#endif
#ifdef SIGMSG
{ SIGMSG, "SIGMSG" },
#endif
{ SIGPIPE, "SIGPIPE" },
#ifdef SIGPOLL
{ SIGPOLL, "SIGPOLL" },
#endif
#ifdef SIGPRE
{ SIGPRE, "SIGPRE" },
#endif
{ SIGPROF, "SIGPROF" },
#ifdef SIGPTY
{ SIGPTY, "SIGPTY" },
#endif
#ifdef SIGPWR
{ SIGPWR, "SIGPWR" },
#endif
{ SIGQUIT, "SIGQUIT" },
#ifdef SIGRECONFIG
{ SIGRECONFIG, "SIGRECONFIG" },
#endif
#ifdef SIGRECOVERY
{ SIGRECOVERY, "SIGRECOVERY" },
#endif
#ifdef SIGRESERVE
{ SIGRESERVE, "SIGRESERVE" },
#endif
#ifdef SIGRETRACT
{ SIGRETRACT, "SIGRETRACT" },
#endif
#ifdef SIGSAK
{ SIGSAK, "SIGSAK" },
#endif
{ SIGSEGV, "SIGSEGV" },
#ifdef SIGSOUND
{ SIGSOUND, "SIGSOUND" },
#endif
#ifdef SIGSTKFLT
{ SIGSTKFLT, "SIGSTKFLT" },
#endif
{ SIGSTOP, "SIGSTOP" },
{ SIGSYS, "SIGSYS" },
#ifdef SIGSYSERROR
{ SIGSYSERROR, "SIGSYSERROR" },
#endif
#ifdef SIGTALRM
{ SIGTALRM, "SIGTALRM" },
#endif
{ SIGTERM, "SIGTERM" },
#ifdef SIGTHAW
{ SIGTHAW, "SIGTHAW" },
#endif
{ SIGTRAP, "SIGTRAP" },
#ifdef SIGTSTP
{ SIGTSTP, "SIGTSTP" },
#endif
{ SIGTTIN, "SIGTTIN" },
{ SIGTTOU, "SIGTTOU" },
#ifdef SIGURG
{ SIGURG, "SIGURG" },
#endif
{ SIGUSR1, "SIGUSR1" },
{ SIGUSR2, "SIGUSR2" },
#ifdef SIGVIRT
{ SIGVIRT, "SIGVIRT" },
#endif
{ SIGVTALRM, "SIGVTALRM" },
#ifdef SIGWAITING
{ SIGWAITING, "SIGWAITING" },
#endif
#ifdef SIGWINCH
{ SIGWINCH, "SIGWINCH" },
#endif
#ifdef SIGWINDOW
{ SIGWINDOW, "SIGWINDOW" },
#endif
{ SIGXCPU, "SIGXCPU" },
{ SIGXFSZ, "SIGXFSZ" },
#ifdef SIGXRES
{ SIGXRES, "SIGXRES" },
#endif
{ -1, NULL }
};
// Returned string is a constant. For unknown signals "UNKNOWN" is returned.
const char* os::Posix::get_signal_name(int sig, char* out, size_t outlen) {
const char* ret = NULL;
#ifdef SIGRTMIN
if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
if (sig == SIGRTMIN) {
ret = "SIGRTMIN";
} else if (sig == SIGRTMAX) {
ret = "SIGRTMAX";
} else {
jio_snprintf(out, outlen, "SIGRTMIN+%d", sig - SIGRTMIN);
return out;
}
}
#endif
if (sig > 0) {
for (int idx = 0; g_signal_info[idx].sig != -1; idx ++) {
if (g_signal_info[idx].sig == sig) {
ret = g_signal_info[idx].name;
break;
}
}
}
if (!ret) {
if (!is_valid_signal(sig)) {
ret = "INVALID";
} else {
ret = "UNKNOWN";
}
}
if (out && outlen > 0) {
strncpy(out, ret, outlen);
out[outlen - 1] = '\0';
}
return out;
}
int os::Posix::get_signal_number(const char* signal_name) {
char tmp[30];
const char* s = signal_name;
if (s[0] != 'S' || s[1] != 'I' || s[2] != 'G') {
jio_snprintf(tmp, sizeof(tmp), "SIG%s", signal_name);
s = tmp;
}
for (int idx = 0; g_signal_info[idx].sig != -1; idx ++) {
if (strcmp(g_signal_info[idx].name, s) == 0) {
return g_signal_info[idx].sig;
}
}
return -1;
}
int os::get_signal_number(const char* signal_name) {
return os::Posix::get_signal_number(signal_name);
}
// Returns true if signal number is valid.
bool os::Posix::is_valid_signal(int sig) {
// MacOS not really POSIX compliant: sigaddset does not return
// an error for invalid signal numbers. However, MacOS does not
// support real time signals and simply seems to have just 33
// signals with no holes in the signal range.
#ifdef __APPLE__
return sig >= 1 && sig < NSIG;
#else
// Use sigaddset to check for signal validity.
sigset_t set;
sigemptyset(&set);
if (sigaddset(&set, sig) == -1 && errno == EINVAL) {
return false;
}
return true;
#endif
}
bool os::Posix::is_sig_ignored(int sig) {
struct sigaction oact;
sigaction(sig, (struct sigaction*)NULL, &oact);
void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction)
: CAST_FROM_FN_PTR(void*, oact.sa_handler);
if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) {
return true;
} else {
return false;
}
}
// Returns:
// NULL for an invalid signal number
// "SIG<num>" for a valid but unknown signal number
// signal name otherwise.
const char* os::exception_name(int sig, char* buf, size_t size) {
if (!os::Posix::is_valid_signal(sig)) {
return NULL;
}
const char* const name = os::Posix::get_signal_name(sig, buf, size);
if (strcmp(name, "UNKNOWN") == 0) {
jio_snprintf(buf, size, "SIG%d", sig);
}
return buf;
}
#define NUM_IMPORTANT_SIGS 32
// Returns one-line short description of a signal set in a user provided buffer.
const char* os::Posix::describe_signal_set_short(const sigset_t* set, char* buffer, size_t buf_size) {
assert(buf_size == (NUM_IMPORTANT_SIGS + 1), "wrong buffer size");
// Note: for shortness, just print out the first 32. That should
// cover most of the useful ones, apart from realtime signals.
for (int sig = 1; sig <= NUM_IMPORTANT_SIGS; sig++) {
const int rc = sigismember(set, sig);
if (rc == -1 && errno == EINVAL) {
buffer[sig-1] = '?';
} else {
buffer[sig-1] = rc == 0 ? '0' : '1';
}
}
buffer[NUM_IMPORTANT_SIGS] = 0;
return buffer;
}
// Prints one-line description of a signal set.
void os::Posix::print_signal_set_short(outputStream* st, const sigset_t* set) {
char buf[NUM_IMPORTANT_SIGS + 1];
os::Posix::describe_signal_set_short(set, buf, sizeof(buf));
st->print("%s", buf);
}
// Writes one-line description of a combination of sigaction.sa_flags into a user
// provided buffer. Returns that buffer.
const char* os::Posix::describe_sa_flags(int flags, char* buffer, size_t size) {
char* p = buffer;
size_t remaining = size;
bool first = true;
int idx = 0;
assert(buffer, "invalid argument");
if (size == 0) {
return buffer;
}
strncpy(buffer, "none", size);
const struct {
// NB: i is an unsigned int here because SA_RESETHAND is on some
// systems 0x80000000, which is implicitly unsigned. Assignining
// it to an int field would be an overflow in unsigned-to-signed
// conversion.
unsigned int i;
const char* s;
} flaginfo [] = {
{ SA_NOCLDSTOP, "SA_NOCLDSTOP" },
{ SA_ONSTACK, "SA_ONSTACK" },
{ SA_RESETHAND, "SA_RESETHAND" },
{ SA_RESTART, "SA_RESTART" },
{ SA_SIGINFO, "SA_SIGINFO" },
{ SA_NOCLDWAIT, "SA_NOCLDWAIT" },
{ SA_NODEFER, "SA_NODEFER" },
#ifdef AIX
{ SA_ONSTACK, "SA_ONSTACK" },
{ SA_OLDSTYLE, "SA_OLDSTYLE" },
#endif
{ 0, NULL }
};
for (idx = 0; flaginfo[idx].s && remaining > 1; idx++) {
if (flags & flaginfo[idx].i) {
if (first) {
jio_snprintf(p, remaining, "%s", flaginfo[idx].s);
first = false;
} else {
jio_snprintf(p, remaining, "|%s", flaginfo[idx].s);
}
const size_t len = strlen(p);
p += len;
remaining -= len;
}
}
buffer[size - 1] = '\0';
return buffer;
}
// Prints one-line description of a combination of sigaction.sa_flags.
void os::Posix::print_sa_flags(outputStream* st, int flags) {
char buffer[0x100];
os::Posix::describe_sa_flags(flags, buffer, sizeof(buffer));
st->print("%s", buffer);
}
// Helper function for os::Posix::print_siginfo_...():
// return a textual description for signal code.
struct enum_sigcode_desc_t {
const char* s_name;
const char* s_desc;
};
static bool get_signal_code_description(const siginfo_t* si, enum_sigcode_desc_t* out) {
const struct {
int sig; int code; const char* s_code; const char* s_desc;
} t1 [] = {
{ SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode." },
{ SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand." },
{ SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode." },
{ SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap." },
{ SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode." },
{ SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register." },
{ SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error." },
{ SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error." },
#if defined(IA64) && defined(LINUX)
{ SIGILL, ILL_BADIADDR, "ILL_BADIADDR", "Unimplemented instruction address" },
{ SIGILL, ILL_BREAK, "ILL_BREAK", "Application Break instruction" },
#endif
{ SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero." },
{ SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow." },
{ SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating-point divide by zero." },
{ SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating-point overflow." },
{ SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating-point underflow." },
{ SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating-point inexact result." },
{ SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating-point operation." },
{ SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range." },
{ SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object." },
{ SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for mapped object." },
#ifdef AIX
// no explanation found what keyerr would be
{ SIGSEGV, SEGV_KEYERR, "SEGV_KEYERR", "key error" },
#endif
#if defined(IA64) && !defined(AIX)
{ SIGSEGV, SEGV_PSTKOVF, "SEGV_PSTKOVF", "Paragraph stack overflow" },
#endif
{ SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment." },
{ SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Nonexistent physical address." },
{ SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object-specific hardware error." },
{ SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint." },
{ SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap." },
{ SIGCHLD, CLD_EXITED, "CLD_EXITED", "Child has exited." },
{ SIGCHLD, CLD_KILLED, "CLD_KILLED", "Child has terminated abnormally and did not create a core file." },
{ SIGCHLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally and created a core file." },
{ SIGCHLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped." },
{ SIGCHLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped." },
{ SIGCHLD, CLD_CONTINUED,"CLD_CONTINUED","Stopped child has continued." },
#ifdef SIGPOLL
{ SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available." },
{ SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available." },
{ SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error." },
{ SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available." },
{ SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected. [Option End]" },
#endif
{ -1, -1, NULL, NULL }
};
// Codes valid in any signal context.
const struct {
int code; const char* s_code; const char* s_desc;
} t2 [] = {
{ SI_USER, "SI_USER", "Signal sent by kill()." },
{ SI_QUEUE, "SI_QUEUE", "Signal sent by the sigqueue()." },
{ SI_TIMER, "SI_TIMER", "Signal generated by expiration of a timer set by timer_settime()." },
{ SI_ASYNCIO, "SI_ASYNCIO", "Signal generated by completion of an asynchronous I/O request." },
{ SI_MESGQ, "SI_MESGQ", "Signal generated by arrival of a message on an empty message queue." },
// Linux specific
#ifdef SI_TKILL
{ SI_TKILL, "SI_TKILL", "Signal sent by tkill (pthread_kill)" },
#endif
#ifdef SI_DETHREAD
{ SI_DETHREAD, "SI_DETHREAD", "Signal sent by execve() killing subsidiary threads" },
#endif
#ifdef SI_KERNEL
{ SI_KERNEL, "SI_KERNEL", "Signal sent by kernel." },
#endif
#ifdef SI_SIGIO
{ SI_SIGIO, "SI_SIGIO", "Signal sent by queued SIGIO" },
#endif
#ifdef AIX
{ SI_UNDEFINED, "SI_UNDEFINED","siginfo contains partial information" },
{ SI_EMPTY, "SI_EMPTY", "siginfo contains no useful information" },
#endif
#ifdef __sun
{ SI_NOINFO, "SI_NOINFO", "No signal information" },
{ SI_RCTL, "SI_RCTL", "kernel generated signal via rctl action" },
{ SI_LWP, "SI_LWP", "Signal sent via lwp_kill" },
#endif
{ -1, NULL, NULL }
};
const char* s_code = NULL;
const char* s_desc = NULL;
for (int i = 0; t1[i].sig != -1; i ++) {
if (t1[i].sig == si->si_signo && t1[i].code == si->si_code) {
s_code = t1[i].s_code;
s_desc = t1[i].s_desc;
break;
}
}
if (s_code == NULL) {
for (int i = 0; t2[i].s_code != NULL; i ++) {
if (t2[i].code == si->si_code) {
s_code = t2[i].s_code;
s_desc = t2[i].s_desc;
}
}
}
if (s_code == NULL) {
out->s_name = "unknown";
out->s_desc = "unknown";
return false;
}
out->s_name = s_code;
out->s_desc = s_desc;
return true;
}
bool os::signal_sent_by_kill(const void* siginfo) {
const siginfo_t* const si = (const siginfo_t*)siginfo;
return si->si_code == SI_USER || si->si_code == SI_QUEUE
#ifdef SI_TKILL
|| si->si_code == SI_TKILL
#endif
;
}
void os::print_siginfo(outputStream* os, const void* si0) {
const siginfo_t* const si = (const siginfo_t*) si0;
char buf[20];
os->print("siginfo:");
if (!si) {
os->print(" <null>");
return;
}
const int sig = si->si_signo;
os->print(" si_signo: %d (%s)", sig, os::Posix::get_signal_name(sig, buf, sizeof(buf)));
enum_sigcode_desc_t ed;
get_signal_code_description(si, &ed);
os->print(", si_code: %d (%s)", si->si_code, ed.s_name);
if (si->si_errno) {
os->print(", si_errno: %d", si->si_errno);
}
// Output additional information depending on the signal code.
// Note: Many implementations lump si_addr, si_pid, si_uid etc. together as unions,
// so it depends on the context which member to use. For synchronous error signals,
// we print si_addr, unless the signal was sent by another process or thread, in
// which case we print out pid or tid of the sender.
if (signal_sent_by_kill(si)) {
const pid_t pid = si->si_pid;
os->print(", si_pid: %ld", (long) pid);
if (IS_VALID_PID(pid)) {
const pid_t me = getpid();
if (me == pid) {
os->print(" (current process)");
}
} else {
os->print(" (invalid)");
}
os->print(", si_uid: %ld", (long) si->si_uid);
if (sig == SIGCHLD) {
os->print(", si_status: %d", si->si_status);
}
} else if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
sig == SIGTRAP || sig == SIGFPE) {
os->print(", si_addr: " PTR_FORMAT, p2i(si->si_addr));
#ifdef SIGPOLL
} else if (sig == SIGPOLL) {
os->print(", si_band: %ld", si->si_band);
#endif
}
}
bool os::signal_thread(Thread* thread, int sig, const char* reason) {
OSThread* osthread = thread->osthread();
if (osthread) {
int status = pthread_kill(osthread->pthread_id(), sig);
if (status == 0) {
Events::log(Thread::current(), "sent signal %d to Thread " INTPTR_FORMAT " because %s.",
sig, p2i(thread), reason);
return true;
}
}
return false;
}
int os::Posix::unblock_thread_signal_mask(const sigset_t *set) {
return pthread_sigmask(SIG_UNBLOCK, set, NULL);
}
address os::Posix::ucontext_get_pc(const ucontext_t* ctx) {
#if defined(AIX)
return Aix::ucontext_get_pc(ctx);
#elif defined(BSD)
return Bsd::ucontext_get_pc(ctx);
#elif defined(LINUX)
return Linux::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) {
#if defined(AIX)
Aix::ucontext_set_pc(ctx, pc);
#elif defined(BSD)
Bsd::ucontext_set_pc(ctx, pc);
#elif defined(LINUX)
Linux::ucontext_set_pc(ctx, pc);
#else
VMError::report_and_die("unimplemented ucontext_get_pc");
#endif
}
char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr) {
size_t stack_size = 0;
size_t guard_size = 0;
@ -1608,22 +1004,6 @@ static void pthread_init_common(void) {
os::PlatformMutex::init();
}
sigset_t sigs;
struct sigaction sigact[NSIG];
struct sigaction* os::Posix::get_preinstalled_handler(int sig) {
if (sigismember(&sigs, sig)) {
return &sigact[sig];
}
return NULL;
}
void os::Posix::save_preinstalled_handler(int sig, struct sigaction& oldAct) {
assert(sig > 0 && sig < NSIG, "vm signal out of expected range");
sigact[sig] = oldAct;
sigaddset(&sigs, sig);
}
// Not all POSIX types and API's are available on all notionally "posix"
// platforms. If we have build-time support then we will check for actual
// runtime support via dlopen/dlsym lookup. This allows for running on an
@ -1726,7 +1106,6 @@ void os::Posix::init_2(void) {
(_pthread_condattr_setclock != NULL ? "" : " not"));
log_info(os)("Relative timed-wait using pthread_cond_timedwait is associated with %s",
_use_clock_monotonic_condattr ? "CLOCK_MONOTONIC" : "the default clock");
sigemptyset(&sigs);
}
#else // !SUPPORTS_CLOCK_MONOTONIC
@ -1739,7 +1118,6 @@ void os::Posix::init_2(void) {
log_info(os)("Use of CLOCK_MONOTONIC is not supported");
log_info(os)("Use of pthread_condattr_setclock is not supported");
log_info(os)("Relative timed-wait using pthread_cond_timedwait is associated with the default clock");
sigemptyset(&sigs);
}
#endif // SUPPORTS_CLOCK_MONOTONIC

@ -63,40 +63,6 @@ public:
static jint set_minimum_stack_sizes();
static size_t get_initial_stack_size(ThreadType thr_type, size_t req_stack_size);
// Returns true if signal is valid.
static bool is_valid_signal(int sig);
static bool is_sig_ignored(int sig);
// Helper function, returns a string (e.g. "SIGILL") for a signal.
// Returned string is a constant. For unknown signals "UNKNOWN" is returned.
static const char* get_signal_name(int sig, char* out, size_t outlen);
// Helper function, returns a signal number for a given signal name, e.g. 11
// for "SIGSEGV". Name can be given with or without "SIG" prefix, so both
// "SEGV" or "SIGSEGV" work. Name must be uppercase.
// Returns -1 for an unknown signal name.
static int get_signal_number(const char* signal_name);
// Returns one-line short description of a signal set in a user provided buffer.
static const char* describe_signal_set_short(const sigset_t* set, char* buffer, size_t size);
// 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);
// Prints a one-line description of a combination of sigaction.sa_flags.
static void print_sa_flags(outputStream* st, int flags);
static address ucontext_get_pc(const ucontext_t* ctx);
// Set PC into context. Needed for continuation after signal.
static void ucontext_set_pc(ucontext_t* ctx, address pc);
// Helper function; describes pthread attributes as short string. String is written
// to buf with len buflen; buf is returned.
static char* describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr);
@ -118,9 +84,6 @@ public:
// effective gid, or if given uid is root.
static bool matches_effective_uid_and_gid_or_root(uid_t uid, gid_t gid);
static struct sigaction *get_preinstalled_handler(int);
static void save_preinstalled_handler(int, struct sigaction&);
static void print_umask(outputStream* st, mode_t umsk);
static void print_user_info(outputStream* st);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,69 @@
/*
* Copyright (c) 2020, 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.
*
*/
#ifndef OS_POSIX_SIGNALS_POSIX_HPP
#define OS_POSIX_SIGNALS_POSIX_HPP
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#include <signal.h>
// Signal number used to suspend/resume a thread
// do not use any signal number less than SIGSEGV, see 4355769
static int SR_signum = SIGUSR2;
class PosixSignals : public AllStatic {
public:
static bool are_signal_handlers_installed();
static void install_signal_handlers();
static bool is_sig_ignored(int sig);
static void signal_sets_init();
// unblocks the signal masks for current thread
static int unblock_thread_signal_mask(const sigset_t *set);
static void hotspot_sigmask(Thread* thread);
static void print_signal_handler(outputStream* st, int sig, char* buf, size_t buflen);
static address ucontext_get_pc(const ucontext_t* ctx);
// Set PC into context. Needed for continuation after signal.
static void ucontext_set_pc(ucontext_t* ctx, address pc);
// Suspend-resume
static int SR_initialize();
static bool do_suspend(OSThread* osthread);
static void do_resume(OSThread* osthread);
// For signal-chaining
static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
// sun.misc.Signal support
static void jdk_misc_signal_init();
};
#endif // OS_POSIX_SIGNALS_POSIX_HPP

@ -27,12 +27,12 @@
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "signals_posix.hpp"
#include "utilities/debug.hpp"
#include "utilities/vmError.hpp"
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#ifdef LINUX
#include <sys/syscall.h>
@ -109,11 +109,11 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
for (int i = 0; i < NUM_SIGNALS; i++) {
sigaddset(&newset, SIGNALS[i]);
}
os::Posix::unblock_thread_signal_mask(&newset);
PosixSignals::unblock_thread_signal_mask(&newset);
// support safefetch faults in error handling
ucontext_t* const uc = (ucontext_t*) ucVoid;
address pc = (uc != NULL) ? os::Posix::ucontext_get_pc(uc) : NULL;
address pc = (uc != NULL) ? PosixSignals::ucontext_get_pc(uc) : NULL;
// Correct pc for SIGILL, SIGFPE (see JDK-8176872)
if (sig == SIGILL || sig == SIGFPE) {
@ -122,7 +122,7 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
// Needed to make it possible to call SafeFetch.. APIs in error handling.
if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
PosixSignals::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return;
}
@ -148,8 +148,7 @@ void VMError::reset_signal_handlers() {
os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
sigaddset(&newset, SIGNALS[i]);
}
os::Posix::unblock_thread_signal_mask(&newset);
PosixSignals::unblock_thread_signal_mask(&newset);
}
// Write a hint to the stream in case siginfo relates to a segv/bus error
@ -170,4 +169,3 @@ void VMError::check_failing_cds_access(outputStream* st, const void* siginfo) {
}
#endif
}

@ -51,6 +51,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
#ifdef COMPILER1
@ -215,7 +216,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE) {
if (os::Aix::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return 1;
} else {
// Ignoring SIGPIPE - see bugs 4229104
@ -225,7 +226,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Aix::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -527,7 +528,7 @@ run_stub:
run_chained_handler:
// signal-chaining
if (os::Aix::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return 1;
}
if (!abort_if_unrecognized) {

@ -49,6 +49,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/align.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
@ -444,7 +445,7 @@ JVM_handle_bsd_signal(int sig,
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (os::Bsd::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
@ -454,7 +455,7 @@ JVM_handle_bsd_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Bsd::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -739,7 +740,7 @@ JVM_handle_bsd_signal(int sig,
}
// signal-chaining
if (os::Bsd::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -53,6 +53,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
@ -143,7 +144,7 @@ JVM_handle_bsd_signal(int sig,
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (os::Bsd::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
@ -153,7 +154,7 @@ JVM_handle_bsd_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Bsd::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -203,7 +204,7 @@ JVM_handle_bsd_signal(int sig,
}
// signal-chaining
if (os::Bsd::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -50,6 +50,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/debug.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
@ -216,7 +217,7 @@ JVM_handle_linux_signal(int sig,
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
@ -234,7 +235,7 @@ JVM_handle_linux_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -425,7 +426,7 @@ JVM_handle_linux_signal(int sig,
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -47,6 +47,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/debug.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
@ -275,7 +276,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
@ -293,7 +294,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -440,7 +441,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -50,6 +50,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/debug.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
@ -237,7 +238,7 @@ JVM_handle_linux_signal(int sig,
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE) {
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE - see bugs 4229104
@ -277,7 +278,7 @@ JVM_handle_linux_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -547,7 +548,7 @@ JVM_handle_linux_signal(int sig,
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -53,6 +53,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/events.hpp"
#include "utilities/debug.hpp"
#include "utilities/vmError.hpp"
@ -257,7 +258,7 @@ JVM_handle_linux_signal(int sig,
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE) {
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
if (PrintMiscellaneous && (WizardMode || Verbose)) {
@ -277,7 +278,7 @@ JVM_handle_linux_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -499,7 +500,7 @@ JVM_handle_linux_signal(int sig,
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -49,6 +49,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
@ -255,7 +256,7 @@ JVM_handle_linux_signal(int sig,
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
@ -273,7 +274,7 @@ JVM_handle_linux_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -554,7 +555,7 @@ JVM_handle_linux_signal(int sig,
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}

@ -48,6 +48,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "signals_posix.hpp"
#include "utilities/align.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
@ -139,7 +140,7 @@ JVM_handle_linux_signal(int sig,
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
@ -149,7 +150,7 @@ JVM_handle_linux_signal(int sig,
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
@ -217,7 +218,7 @@ JVM_handle_linux_signal(int sig,
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}