src/os/linux/vm/jsig.c

Fri, 11 Jul 2008 01:14:44 -0700

author
trims
date
Fri, 11 Jul 2008 01:14:44 -0700
changeset 670
9c2ecc2ffb12
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright 2001-2006 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 <signal.h>
    34 #include <dlfcn.h>
    35 #include <pthread.h>
    36 #include <stdio.h>
    37 #include <stdlib.h>
    39 #define bool int
    40 #define true 1
    41 #define false 0
    43 #define MAXSIGNUM 32
    44 #define MASK(sig) ((unsigned int)1 << sig)
    46 static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
    47 static unsigned int jvmsigs = 0; /* signals used by jvm */
    49 /* used to synchronize the installation of signal handlers */
    50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    51 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    52 static pthread_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;
    65 static void signal_lock() {
    66   pthread_mutex_lock(&mutex);
    67   /* When the jvm is installing its set of signal handlers, threads
    68    * other than the jvm thread should wait */
    69   if (jvm_signal_installing) {
    70     if (tid != pthread_self()) {
    71       pthread_cond_wait(&cond, &mutex);
    72     }
    73   }
    74 }
    76 static void signal_unlock() {
    77   pthread_mutex_unlock(&mutex);
    78 }
    80 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
    81                                    bool is_sigset) {
    82   if (os_signal == NULL) {
    83     if (!is_sigset) {
    84       os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
    85     } else {
    86       os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
    87     }
    88     if (os_signal == NULL) {
    89       printf("%s\n", dlerror());
    90       exit(0);
    91     }
    92   }
    93   return (*os_signal)(sig, disp);
    94 }
    96 static void save_signal_handler(int sig, sa_handler_t disp) {
    97   sigset_t set;
    98   sact[sig].sa_handler = disp;
    99   sigemptyset(&set);
   100   sact[sig].sa_mask = set;
   101   sact[sig].sa_flags = 0;
   102 }
   104 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
   105   sa_handler_t oldhandler;
   106   bool sigused;
   108   signal_lock();
   110   sigused = (MASK(sig) & jvmsigs) != 0;
   111   if (jvm_signal_installed && sigused) {
   112     /* jvm has installed its signal handler for this signal. */
   113     /* Save the handler. Don't really install it. */
   114     oldhandler = sact[sig].sa_handler;
   115     save_signal_handler(sig, disp);
   117     signal_unlock();
   118     return oldhandler;
   119   } else if (jvm_signal_installing) {
   120     /* jvm is installing its signal handlers. Install the new
   121      * handlers and save the old ones. jvm uses sigaction().
   122      * Leave the piece here just in case. */
   123     oldhandler = call_os_signal(sig, disp, is_sigset);
   124     save_signal_handler(sig, oldhandler);
   126     /* Record the signals used by jvm */
   127     jvmsigs |= MASK(sig);
   129     signal_unlock();
   130     return oldhandler;
   131   } else {
   132     /* jvm has no relation with this signal (yet). Install the
   133      * the handler. */
   134     oldhandler = call_os_signal(sig, disp, is_sigset);
   136     signal_unlock();
   137     return oldhandler;
   138   }
   139 }
   141 sa_handler_t signal(int sig, sa_handler_t disp) {
   142   return set_signal(sig, disp, false);
   143 }
   145 sa_handler_t sigset(int sig, sa_handler_t disp) {
   146   return set_signal(sig, disp, true);
   147  }
   149 static int call_os_sigaction(int sig, const struct sigaction  *act,
   150                              struct sigaction *oact) {
   151   if (os_sigaction == NULL) {
   152     os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
   153     if (os_sigaction == NULL) {
   154       printf("%s\n", dlerror());
   155       exit(0);
   156     }
   157   }
   158   return (*os_sigaction)(sig, act, oact);
   159 }
   161 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
   162   int res;
   163   bool sigused;
   164   struct sigaction oldAct;
   166   signal_lock();
   168   sigused = (MASK(sig) & jvmsigs) != 0;
   169   if (jvm_signal_installed && sigused) {
   170     /* jvm has installed its signal handler for this signal. */
   171     /* Save the handler. Don't really install it. */
   172     if (oact != NULL) {
   173       *oact = sact[sig];
   174     }
   175     if (act != NULL) {
   176       sact[sig] = *act;
   177     }
   179     signal_unlock();
   180     return 0;
   181   } else if (jvm_signal_installing) {
   182     /* jvm is installing its signal handlers. Install the new
   183      * handlers and save the old ones. */
   184     res = call_os_sigaction(sig, act, &oldAct);
   185     sact[sig] = oldAct;
   186     if (oact != NULL) {
   187       *oact = oldAct;
   188     }
   190     /* Record the signals used by jvm */
   191     jvmsigs |= MASK(sig);
   193     signal_unlock();
   194     return res;
   195   } else {
   196     /* jvm has no relation with this signal (yet). Install the
   197      * the handler. */
   198     res = call_os_sigaction(sig, act, oact);
   200     signal_unlock();
   201     return res;
   202   }
   203 }
   205 /* The three functions for the jvm to call into */
   206 void JVM_begin_signal_setting() {
   207   signal_lock();
   208   jvm_signal_installing = true;
   209   tid = pthread_self();
   210   signal_unlock();
   211 }
   213 void JVM_end_signal_setting() {
   214   signal_lock();
   215   jvm_signal_installed = true;
   216   jvm_signal_installing = false;
   217   pthread_cond_broadcast(&cond);
   218   signal_unlock();
   219 }
   221 struct sigaction *JVM_get_signal_action(int sig) {
   222   /* Does race condition make sense here? */
   223   if ((MASK(sig) & jvmsigs) != 0) {
   224     return &sact[sig];
   225   }
   226   return NULL;
   227 }

mercurial