src/os/solaris/vm/jsig.c

Thu, 19 Mar 2009 09:13:24 -0700

author
kvn
date
Thu, 19 Mar 2009 09:13:24 -0700
changeset 1082
bd441136a5ce
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright 2001-2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 /* CopyrightVersion 1.2 */
    27 /* This is a special library that should be loaded before libc &
    28  * libthread to interpose the signal handler installation functions:
    29  * sigaction(), signal(), sigset().
    30  * Used for signal-chaining. See RFE 4381843.
    31  */
    33 #include <stdlib.h>
    34 #include <stdio.h>
    35 #include <string.h>
    36 #include <signal.h>
    37 #include <dlfcn.h>
    38 #include <thread.h>
    39 #include <synch.h>
    40 #include "jvm_solaris.h"
    42 #define bool int
    43 #define true 1
    44 #define false 0
    46 static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
    47 static sigset_t jvmsigs;
    49 /* used to synchronize the installation of signal handlers */
    50 static mutex_t mutex = DEFAULTMUTEX;
    51 static cond_t cond = DEFAULTCV;
    52 static thread_t tid = 0;
    54 typedef void (*sa_handler_t)(int);
    55 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
    56 typedef sa_handler_t (*signal_t)(int, sa_handler_t);
    57 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
    59 static signal_t os_signal = 0; /* os's version of signal()/sigset() */
    60 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
    62 static bool jvm_signal_installing = false;
    63 static bool jvm_signal_installed = false;
    66 /* assume called within signal_lock */
    67 static void allocate_sact() {
    68   size_t maxsignum;
    69   maxsignum = SIGRTMAX;
    70   if (sact == NULL) {
    71     sact = (struct sigaction *)malloc((maxsignum+1) * (size_t)sizeof(struct sigaction));
    72     memset(sact, 0, (maxsignum+1) * (size_t)sizeof(struct sigaction));
    73   }
    75   if (sact == NULL) {
    76     printf("%s\n", "libjsig.so unable to allocate memory");
    77     exit(0);
    78   }
    80   sigemptyset(&jvmsigs);
    81 }
    83 static void signal_lock() {
    84   mutex_lock(&mutex);
    85   /* When the jvm is installing its set of signal handlers, threads
    86    * other than the jvm thread should wait */
    87   if (jvm_signal_installing) {
    88     if (tid != thr_self()) {
    89       cond_wait(&cond, &mutex);
    90     }
    91   }
    92 }
    94 static void signal_unlock() {
    95   mutex_unlock(&mutex);
    96 }
    98 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
    99                                    bool is_sigset) {
   100   if (os_signal == NULL) {
   101     if (!is_sigset) {
   102       os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
   103     } else {
   104       os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
   105     }
   106     if (os_signal == NULL) {
   107       printf("%s\n", dlerror());
   108       exit(0);
   109     }
   110   }
   111   return (*os_signal)(sig, disp);
   112 }
   114 static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
   115   sigset_t set;
   116   if (sact == NULL) {
   117     allocate_sact();
   118   }
   119   sact[sig].sa_handler = disp;
   120   sigemptyset(&set);
   121   sact[sig].sa_mask = set;
   122   if (!is_sigset) {
   123     sact[sig].sa_flags = SA_NODEFER;
   124     if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
   125       sact[sig].sa_flags |= SA_RESETHAND;
   126     }
   127   } else {
   128     sact[sig].sa_flags = 0;
   129   }
   130 }
   132 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
   133   sa_handler_t oldhandler;
   134   bool sigblocked;
   136   signal_lock();
   137   if (sact == NULL) {
   138     allocate_sact();
   139   }
   141   if (jvm_signal_installed && sigismember(&jvmsigs, sig)) {
   142     /* jvm has installed its signal handler for this signal. */
   143     /* Save the handler. Don't really install it. */
   144     if (is_sigset) {
   145       /* We won't honor the SIG_HOLD request to change the signal mask */
   146       sigblocked = sigismember(&(sact[sig].sa_mask), sig);
   147     }
   148     oldhandler = sact[sig].sa_handler;
   149     save_signal_handler(sig, disp, is_sigset);
   151     if (is_sigset && sigblocked) {
   152       oldhandler = SIG_HOLD;
   153     }
   155     signal_unlock();
   156     return oldhandler;
   157   } else if (jvm_signal_installing) {
   158     /* jvm is installing its signal handlers. Install the new
   159      * handlers and save the old ones. jvm uses sigaction().
   160      * Leave the piece here just in case. */
   161     oldhandler = call_os_signal(sig, disp, is_sigset);
   162     save_signal_handler(sig, oldhandler, is_sigset);
   164     /* Record the signals used by jvm */
   165     sigaddset(&jvmsigs, sig);
   167     signal_unlock();
   168     return oldhandler;
   169   } else {
   170     /* jvm has no relation with this signal (yet). Install the
   171      * the handler. */
   172     oldhandler = call_os_signal(sig, disp, is_sigset);
   174     signal_unlock();
   175     return oldhandler;
   176   }
   177 }
   179 sa_handler_t signal(int sig, sa_handler_t disp) {
   180   return set_signal(sig, disp, false);
   181 }
   183 sa_handler_t sigset(int sig, sa_handler_t disp) {
   184   return set_signal(sig, disp, true);
   185 }
   187 static int call_os_sigaction(int sig, const struct sigaction  *act,
   188                              struct sigaction *oact) {
   189   if (os_sigaction == NULL) {
   190     os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
   191     if (os_sigaction == NULL) {
   192       printf("%s\n", dlerror());
   193       exit(0);
   194     }
   195   }
   196   return (*os_sigaction)(sig, act, oact);
   197 }
   199 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
   200   int res;
   201   struct sigaction oldAct;
   203   signal_lock();
   205   if (sact == NULL ) {
   206     allocate_sact();
   207   }
   208   if (jvm_signal_installed && sigismember(&jvmsigs, sig)) {
   209     /* jvm has installed its signal handler for this signal. */
   210     /* Save the handler. Don't really install it. */
   211     if (oact != NULL) {
   212       *oact = sact[sig];
   213     }
   214     if (act != NULL) {
   215       sact[sig] = *act;
   216     }
   218     signal_unlock();
   219     return 0;
   220   } else if (jvm_signal_installing) {
   221     /* jvm is installing its signal handlers. Install the new
   222      * handlers and save the old ones. */
   223     res = call_os_sigaction(sig, act, &oldAct);
   224     sact[sig] = oldAct;
   225     if (oact != NULL) {
   226       *oact = oldAct;
   227     }
   229     /* Record the signals used by jvm */
   230     sigaddset(&jvmsigs, sig);
   232     signal_unlock();
   233     return res;
   234   } else {
   235     /* jvm has no relation with this signal (yet). Install the
   236      * the handler. */
   237     res = call_os_sigaction(sig, act, oact);
   239     signal_unlock();
   240     return res;
   241   }
   242 }
   244 /* The four functions for the jvm to call into */
   245 void JVM_begin_signal_setting() {
   246   signal_lock();
   247   jvm_signal_installing = true;
   248   tid = thr_self();
   249   signal_unlock();
   250 }
   252 void JVM_end_signal_setting() {
   253   signal_lock();
   254   jvm_signal_installed = true;
   255   jvm_signal_installing = false;
   256   cond_broadcast(&cond);
   257   signal_unlock();
   258 }
   260 struct sigaction *JVM_get_signal_action(int sig) {
   261   if (sact == NULL) {
   262     allocate_sact();
   263   }
   264   /* Does race condition make sense here? */
   265   if (sigismember(&jvmsigs, sig)) {
   266     return &sact[sig];
   267   }
   268   return NULL;
   269 }
   271 int JVM_get_libjsig_version() {
   272   return JSIG_VERSION_1_4_1;
   273 }

mercurial