< prev index next >

src/java.base/unix/native/libjsig/jsig.c

Print this page
rev 59105 : imported patch corelibs


  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any
  24  * questions.
  25  *
  26  */
  27 
  28 /* This is a special library that should be loaded before libc &
  29  * libthread to interpose the signal handler installation functions:
  30  * sigaction(), signal(), sigset().
  31  * Used for signal-chaining. See RFE 4381843.
  32  */
  33 
  34 #include "jni.h"
  35 
  36 #ifdef SOLARIS
  37 /* Our redeclarations of the system functions must not have a less
  38  * restrictive linker scoping, so we have to declare them as JNIEXPORT
  39  * before including signal.h */
  40 #include "sys/signal.h"
  41 JNIEXPORT void (*signal(int sig, void (*disp)(int)))(int);
  42 JNIEXPORT void (*sigset(int sig, void (*disp)(int)))(int);
  43 JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
  44 #endif
  45 
  46 #include <dlfcn.h>
  47 #include <errno.h>
  48 #include <pthread.h>
  49 #include <signal.h>
  50 #include <stdio.h>
  51 #include <stdlib.h>
  52 #include <string.h>
  53 
  54 #if (__STDC_VERSION__ >= 199901L)
  55   #include <stdbool.h>
  56 #else
  57   #define bool int
  58   #define true 1
  59   #define false 0
  60 #endif
  61 
  62 #ifdef SOLARIS
  63 #define MAX_SIGNALS (SIGRTMAX+1)
  64 
  65 /* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */
  66 static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
  67 #else
  68 #define MAX_SIGNALS NSIG
  69 
  70 static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */
  71 #endif
  72 
  73 static sigset_t jvmsigs; /* Signals used by jvm. */
  74 
  75 #ifdef MACOSX
  76 static __thread bool reentry = false; /* prevent reentry deadlock (per-thread) */
  77 #endif
  78 
  79 /* Used to synchronize the installation of signal handlers. */
  80 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  81 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  82 static pthread_t tid;
  83 
  84 typedef void (*sa_handler_t)(int);
  85 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
  86 typedef sa_handler_t (*signal_function_t)(int, sa_handler_t);
  87 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
  88 
  89 static signal_function_t os_signal = 0; /* os's version of signal()/sigset() */
  90 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
  91 
  92 static bool jvm_signal_installing = false;
  93 static bool jvm_signal_installed = false;
  94 
  95 
  96 /* assume called within signal_lock */
  97 static void allocate_sact() {
  98 #ifdef SOLARIS
  99   if (sact == NULL) {
 100     sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
 101     if (sact == NULL) {
 102       printf("%s\n", "libjsig.so unable to allocate memory");
 103       exit(0);
 104     }
 105     memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
 106   }
 107 #endif
 108 }
 109 
 110 static void signal_lock() {
 111   pthread_mutex_lock(&mutex);
 112   /* When the jvm is installing its set of signal handlers, threads
 113    * other than the jvm thread should wait. */
 114   if (jvm_signal_installing) {
 115     /* tid is not initialized until jvm_signal_installing is set to true. */
 116     if (pthread_equal(tid, pthread_self()) == 0) {
 117       do {
 118         pthread_cond_wait(&cond, &mutex);
 119       } while (jvm_signal_installing);
 120     }
 121   }
 122 }
 123 
 124 static void signal_unlock() {
 125   pthread_mutex_unlock(&mutex);
 126 }
 127 
 128 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
 129                                    bool is_sigset) {


 145   /* On macosx, the OS implementation of signal calls sigaction.
 146    * Make sure we do not deadlock with ourself. (See JDK-8072147). */
 147   reentry = true;
 148 #endif
 149 
 150   res = (*os_signal)(sig, disp);
 151 
 152 #ifdef MACOSX
 153   reentry = false;
 154 #endif
 155 
 156   return res;
 157 }
 158 
 159 static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
 160   sigset_t set;
 161 
 162   sact[sig].sa_handler = disp;
 163   sigemptyset(&set);
 164   sact[sig].sa_mask = set;
 165   if (!is_sigset) {
 166 #ifdef SOLARIS
 167     sact[sig].sa_flags = SA_NODEFER;
 168     if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
 169       sact[sig].sa_flags |= SA_RESETHAND;
 170     }
 171 #else
 172     sact[sig].sa_flags = 0;
 173 #endif
 174   } else {
 175     sact[sig].sa_flags = 0;
 176   }
 177 }
 178 
 179 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
 180   sa_handler_t oldhandler;
 181   bool sigused;
 182   bool sigblocked;
 183 
 184   signal_lock();
 185   allocate_sact();
 186 
 187   sigused = sigismember(&jvmsigs, sig);
 188   if (jvm_signal_installed && sigused) {
 189     /* jvm has installed its signal handler for this signal. */
 190     /* Save the handler. Don't really install it. */
 191     if (is_sigset) {
 192       sigblocked = sigismember(&(sact[sig].sa_mask), sig);
 193     }
 194     oldhandler = sact[sig].sa_handler;
 195     save_signal_handler(sig, disp, is_sigset);
 196 
 197 #ifdef SOLARIS
 198     if (is_sigset && sigblocked) {
 199       /* We won't honor the SIG_HOLD request to change the signal mask */
 200       oldhandler = SIG_HOLD;
 201     }
 202 #endif
 203 
 204     signal_unlock();
 205     return oldhandler;
 206   } else if (jvm_signal_installing) {
 207     /* jvm is installing its signal handlers. Install the new
 208      * handlers and save the old ones. jvm uses sigaction().
 209      * Leave the piece here just in case. */
 210     oldhandler = call_os_signal(sig, disp, is_sigset);
 211     save_signal_handler(sig, oldhandler, is_sigset);
 212 
 213     /* Record the signals used by jvm */
 214     sigaddset(&jvmsigs, sig);
 215 
 216     signal_unlock();
 217     return oldhandler;
 218   } else {
 219     /* jvm has no relation with this signal (yet). Install the
 220      * the handler. */
 221     oldhandler = call_os_signal(sig, disp, is_sigset);
 222 
 223     signal_unlock();


 261 }
 262 
 263 JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
 264   int res;
 265   bool sigused;
 266   struct sigaction oldAct;
 267 
 268   if (sig < 0 || sig >= MAX_SIGNALS) {
 269     errno = EINVAL;
 270     return -1;
 271   }
 272 
 273 #ifdef MACOSX
 274   if (reentry) {
 275     return call_os_sigaction(sig, act, oact);
 276   }
 277 #endif
 278 
 279   signal_lock();
 280 
 281   allocate_sact();
 282   sigused = sigismember(&jvmsigs, sig);
 283   if (jvm_signal_installed && sigused) {
 284     /* jvm has installed its signal handler for this signal. */
 285     /* Save the handler. Don't really install it. */
 286     if (oact != NULL) {
 287       *oact = sact[sig];
 288     }
 289     if (act != NULL) {
 290       sact[sig] = *act;
 291     }
 292 
 293     signal_unlock();
 294     return 0;
 295   } else if (jvm_signal_installing) {
 296     /* jvm is installing its signal handlers. Install the new
 297      * handlers and save the old ones. */
 298     res = call_os_sigaction(sig, act, &oldAct);
 299     sact[sig] = oldAct;
 300     if (oact != NULL) {
 301       *oact = oldAct;


 317 }
 318 
 319 /* The three functions for the jvm to call into. */
 320 JNIEXPORT void JVM_begin_signal_setting() {
 321   signal_lock();
 322   sigemptyset(&jvmsigs);
 323   jvm_signal_installing = true;
 324   tid = pthread_self();
 325   signal_unlock();
 326 }
 327 
 328 JNIEXPORT void JVM_end_signal_setting() {
 329   signal_lock();
 330   jvm_signal_installed = true;
 331   jvm_signal_installing = false;
 332   pthread_cond_broadcast(&cond);
 333   signal_unlock();
 334 }
 335 
 336 JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {
 337   allocate_sact();
 338   /* Does race condition make sense here? */
 339   if (sigismember(&jvmsigs, sig)) {
 340     return &sact[sig];
 341   }
 342   return NULL;
 343 }


  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any
  24  * questions.
  25  *
  26  */
  27 
  28 /* This is a special library that should be loaded before libc &
  29  * libthread to interpose the signal handler installation functions:
  30  * sigaction(), signal(), sigset().
  31  * Used for signal-chaining. See RFE 4381843.
  32  */
  33 
  34 #include "jni.h"
  35 










  36 #include <dlfcn.h>
  37 #include <errno.h>
  38 #include <pthread.h>
  39 #include <signal.h>
  40 #include <stdio.h>
  41 #include <stdlib.h>
  42 #include <string.h>
  43 
  44 #if (__STDC_VERSION__ >= 199901L)
  45   #include <stdbool.h>
  46 #else
  47   #define bool int
  48   #define true 1
  49   #define false 0
  50 #endif
  51 






  52 #define MAX_SIGNALS NSIG
  53 
  54 static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */

  55 
  56 static sigset_t jvmsigs; /* Signals used by jvm. */
  57 
  58 #ifdef MACOSX
  59 static __thread bool reentry = false; /* prevent reentry deadlock (per-thread) */
  60 #endif
  61 
  62 /* Used to synchronize the installation of signal handlers. */
  63 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  64 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  65 static pthread_t tid;
  66 
  67 typedef void (*sa_handler_t)(int);
  68 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
  69 typedef sa_handler_t (*signal_function_t)(int, sa_handler_t);
  70 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
  71 
  72 static signal_function_t os_signal = 0; /* os's version of signal()/sigset() */
  73 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
  74 
  75 static bool jvm_signal_installing = false;
  76 static bool jvm_signal_installed = false;
  77 
  78 














  79 static void signal_lock() {
  80   pthread_mutex_lock(&mutex);
  81   /* When the jvm is installing its set of signal handlers, threads
  82    * other than the jvm thread should wait. */
  83   if (jvm_signal_installing) {
  84     /* tid is not initialized until jvm_signal_installing is set to true. */
  85     if (pthread_equal(tid, pthread_self()) == 0) {
  86       do {
  87         pthread_cond_wait(&cond, &mutex);
  88       } while (jvm_signal_installing);
  89     }
  90   }
  91 }
  92 
  93 static void signal_unlock() {
  94   pthread_mutex_unlock(&mutex);
  95 }
  96 
  97 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
  98                                    bool is_sigset) {


 114   /* On macosx, the OS implementation of signal calls sigaction.
 115    * Make sure we do not deadlock with ourself. (See JDK-8072147). */
 116   reentry = true;
 117 #endif
 118 
 119   res = (*os_signal)(sig, disp);
 120 
 121 #ifdef MACOSX
 122   reentry = false;
 123 #endif
 124 
 125   return res;
 126 }
 127 
 128 static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
 129   sigset_t set;
 130 
 131   sact[sig].sa_handler = disp;
 132   sigemptyset(&set);
 133   sact[sig].sa_mask = set;










 134   sact[sig].sa_flags = 0;

 135 }
 136 
 137 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
 138   sa_handler_t oldhandler;
 139   bool sigused;
 140   bool sigblocked;
 141 
 142   signal_lock();

 143 
 144   sigused = sigismember(&jvmsigs, sig);
 145   if (jvm_signal_installed && sigused) {
 146     /* jvm has installed its signal handler for this signal. */
 147     /* Save the handler. Don't really install it. */
 148     if (is_sigset) {
 149       sigblocked = sigismember(&(sact[sig].sa_mask), sig);
 150     }
 151     oldhandler = sact[sig].sa_handler;
 152     save_signal_handler(sig, disp, is_sigset);
 153 







 154     signal_unlock();
 155     return oldhandler;
 156   } else if (jvm_signal_installing) {
 157     /* jvm is installing its signal handlers. Install the new
 158      * handlers and save the old ones. jvm uses sigaction().
 159      * Leave the piece here just in case. */
 160     oldhandler = call_os_signal(sig, disp, is_sigset);
 161     save_signal_handler(sig, oldhandler, is_sigset);
 162 
 163     /* Record the signals used by jvm */
 164     sigaddset(&jvmsigs, sig);
 165 
 166     signal_unlock();
 167     return oldhandler;
 168   } else {
 169     /* jvm has no relation with this signal (yet). Install the
 170      * the handler. */
 171     oldhandler = call_os_signal(sig, disp, is_sigset);
 172 
 173     signal_unlock();


 211 }
 212 
 213 JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
 214   int res;
 215   bool sigused;
 216   struct sigaction oldAct;
 217 
 218   if (sig < 0 || sig >= MAX_SIGNALS) {
 219     errno = EINVAL;
 220     return -1;
 221   }
 222 
 223 #ifdef MACOSX
 224   if (reentry) {
 225     return call_os_sigaction(sig, act, oact);
 226   }
 227 #endif
 228 
 229   signal_lock();
 230 

 231   sigused = sigismember(&jvmsigs, sig);
 232   if (jvm_signal_installed && sigused) {
 233     /* jvm has installed its signal handler for this signal. */
 234     /* Save the handler. Don't really install it. */
 235     if (oact != NULL) {
 236       *oact = sact[sig];
 237     }
 238     if (act != NULL) {
 239       sact[sig] = *act;
 240     }
 241 
 242     signal_unlock();
 243     return 0;
 244   } else if (jvm_signal_installing) {
 245     /* jvm is installing its signal handlers. Install the new
 246      * handlers and save the old ones. */
 247     res = call_os_sigaction(sig, act, &oldAct);
 248     sact[sig] = oldAct;
 249     if (oact != NULL) {
 250       *oact = oldAct;


 266 }
 267 
 268 /* The three functions for the jvm to call into. */
 269 JNIEXPORT void JVM_begin_signal_setting() {
 270   signal_lock();
 271   sigemptyset(&jvmsigs);
 272   jvm_signal_installing = true;
 273   tid = pthread_self();
 274   signal_unlock();
 275 }
 276 
 277 JNIEXPORT void JVM_end_signal_setting() {
 278   signal_lock();
 279   jvm_signal_installed = true;
 280   jvm_signal_installing = false;
 281   pthread_cond_broadcast(&cond);
 282   signal_unlock();
 283 }
 284 
 285 JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {

 286   /* Does race condition make sense here? */
 287   if (sigismember(&jvmsigs, sig)) {
 288     return &sact[sig];
 289   }
 290   return NULL;
 291 }
< prev index next >