< prev index next >

hotspot/src/os/bsd/vm/jsig.c

Print this page
rev 7434 : 8072147: Preloading libjsig.dylib causes deadlock when signal() is called
Summary: Added check to prevent reentry of signal chaining code
Reviewed-by: dcubed, acorn, dholmes

*** 1,7 **** /* ! * Copyright (c) 2001, 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. --- 1,7 ---- /* ! * Copyright (c) 2001, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 34,50 **** --- 34,54 ---- #include <dlfcn.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> + #include <string.h> #define MAXSIGNUM 32 #define MASK(sig) ((unsigned int)1 << sig) static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */ static unsigned int jvmsigs = 0; /* signals used by jvm */ + static pthread_key_t reentry_flag_key; + static pthread_once_t reentry_key_init_once = PTHREAD_ONCE_INIT; + /* used to synchronize the installation of signal handlers */ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_t tid = 0;
*** 57,66 **** --- 61,79 ---- static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ static bool jvm_signal_installing = false; static bool jvm_signal_installed = false; + #define check_status(cmd) \ + do { \ + int status = (cmd); \ + if (status != 0) { \ + printf("error %s (%d) in " #cmd "\n", strerror(status), status); \ + exit(1); \ + } \ + } while (0) + static void signal_lock() { pthread_mutex_lock(&mutex); /* When the jvm is installing its set of signal handlers, threads * other than the jvm thread should wait */ if (jvm_signal_installing) {
*** 72,83 **** --- 85,103 ---- static void signal_unlock() { pthread_mutex_unlock(&mutex); } + static void reentry_tls_init() { + // value for reentry_flag_key will default to NULL (false) + check_status(pthread_key_create(&reentry_flag_key, NULL)); + } + static sa_handler_t call_os_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t res; + if (os_signal == NULL) { if (!is_sigset) { os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); } else { os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
*** 85,95 **** if (os_signal == NULL) { printf("%s\n", dlerror()); exit(0); } } ! return (*os_signal)(sig, disp); } static void save_signal_handler(int sig, sa_handler_t disp) { sigset_t set; sact[sig].sa_handler = disp; --- 105,120 ---- if (os_signal == NULL) { printf("%s\n", dlerror()); exit(0); } } ! check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); ! // set reentry_flag_key to non-NULL to show reentry ! check_status(pthread_setspecific(reentry_flag_key, &res)); ! res = (*os_signal)(sig, disp); ! check_status(pthread_setspecific(reentry_flag_key, NULL)); ! return res; } static void save_signal_handler(int sig, sa_handler_t disp) { sigset_t set; sact[sig].sa_handler = disp;
*** 159,168 **** --- 184,198 ---- int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { int res; bool sigused; struct sigaction oldAct; + check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); + if (pthread_getspecific(reentry_flag_key) != NULL) { + return call_os_sigaction(sig, act, oact); + } + signal_lock(); sigused = (MASK(sig) & jvmsigs) != 0; if (jvm_signal_installed && sigused) { /* jvm has installed its signal handler for this signal. */
< prev index next >