Back to index

glibc  2.9
sigaction.c
Go to the documentation of this file.
00001 /* POSIX.1 `sigaction' call for Linux/i386.
00002    Copyright (C) 1991,1995-2000,2002-2005,2006 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <sysdep.h>
00021 #include <errno.h>
00022 #include <stddef.h>
00023 #include <signal.h>
00024 #include <string.h>
00025 
00026 #include <sysdep.h>
00027 #include <sys/syscall.h>
00028 #include <ldsodefs.h>
00029 
00030 #include <kernel-features.h>
00031 
00032 /* The difference here is that the sigaction structure used in the
00033    kernel is not the same as we use in the libc.  Therefore we must
00034    translate it here.  */
00035 #include <kernel_sigaction.h>
00036 
00037 /* We do not globally define the SA_RESTORER flag so do it here.  */
00038 #define SA_RESTORER 0x04000000
00039 
00040 
00041 #if __ASSUME_REALTIME_SIGNALS == 0
00042 /* The variable is shared between all wrappers around signal handling
00043    functions which have RT equivalents.  */
00044 int __libc_missing_rt_sigs;
00045 #endif
00046 
00047 /* Using the hidden attribute here does not change the code but it
00048    helps to avoid warnings.  */
00049 #ifdef __NR_rt_sigaction
00050 extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
00051 #endif
00052 extern void restore (void) asm ("__restore") attribute_hidden;
00053 
00054 
00055 /* If ACT is not NULL, change the action for SIG to *ACT.
00056    If OACT is not NULL, put the old action for SIG in *OACT.  */
00057 int
00058 __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
00059 {
00060 #if __ASSUME_REALTIME_SIGNALS == 0
00061   struct old_kernel_sigaction k_newact, k_oldact;
00062 #endif
00063   int result;
00064 
00065 #ifdef __NR_rt_sigaction
00066 
00067   /* First try the RT signals.  */
00068 # if __ASSUME_REALTIME_SIGNALS == 0
00069   if (!__libc_missing_rt_sigs)
00070 # endif
00071     {
00072       struct kernel_sigaction kact, koact;
00073 # if __ASSUME_REALTIME_SIGNALS == 0
00074       int saved_errno = errno;
00075 # endif
00076 
00077       if (act)
00078        {
00079          kact.k_sa_handler = act->sa_handler;
00080          kact.sa_flags = act->sa_flags;
00081          memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
00082 
00083          if (GLRO(dl_sysinfo_dso) == NULL)
00084            {
00085              kact.sa_flags |= SA_RESTORER;
00086 
00087              kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
00088                               ? &restore_rt : &restore);
00089            }
00090        }
00091 
00092       /* XXX The size argument hopefully will have to be changed to the
00093         real size of the user-level sigset_t.  */
00094       result = INLINE_SYSCALL (rt_sigaction, 4,
00095                             sig, act ? __ptrvalue (&kact) : NULL,
00096                             oact ? __ptrvalue (&koact) : NULL, _NSIG / 8);
00097 
00098 # if __ASSUME_REALTIME_SIGNALS == 0
00099       if (result >= 0 || errno != ENOSYS)
00100 # endif
00101        {
00102          if (oact && result >= 0)
00103            {
00104              oact->sa_handler = koact.k_sa_handler;
00105              memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
00106              oact->sa_flags = koact.sa_flags;
00107              oact->sa_restorer = koact.sa_restorer;
00108            }
00109          return result;
00110        }
00111 
00112 # if __ASSUME_REALTIME_SIGNALS == 0
00113       __set_errno (saved_errno);
00114       __libc_missing_rt_sigs = 1;
00115 # endif
00116     }
00117 #endif
00118 
00119 #if __ASSUME_REALTIME_SIGNALS == 0
00120   if (act)
00121     {
00122       k_newact.k_sa_handler = act->sa_handler;
00123       k_newact.sa_mask = act->sa_mask.__val[0];
00124       k_newact.sa_flags = act->sa_flags | SA_RESTORER;
00125 
00126       k_newact.sa_restorer = &restore;
00127     }
00128 
00129   result = INLINE_SYSCALL (sigaction, 3, sig,
00130                         act ? __ptrvalue (&k_newact) : 0,
00131                         oact ? __ptrvalue (&k_oldact) : 0);
00132 
00133   if (result < 0)
00134     return -1;
00135 
00136   if (oact)
00137     {
00138       oact->sa_handler = k_oldact.k_sa_handler;
00139       oact->sa_mask.__val[0] = k_oldact.sa_mask;
00140       oact->sa_flags = k_oldact.sa_flags;
00141       oact->sa_restorer = k_oldact.sa_restorer;
00142     }
00143 
00144   return 0;
00145 #endif
00146 }
00147 libc_hidden_def (__libc_sigaction)
00148 
00149 #ifdef WRAPPER_INCLUDE
00150 # include WRAPPER_INCLUDE
00151 #endif
00152 
00153 #ifndef LIBC_SIGACTION
00154 weak_alias (__libc_sigaction, __sigaction)
00155 libc_hidden_weak (__sigaction)
00156 weak_alias (__libc_sigaction, sigaction)
00157 #endif
00158 
00159 /* NOTE: Please think twice before making any changes to the bits of
00160    code below.  GDB needs some intimate knowledge about it to
00161    recognize them as signal trampolines, and make backtraces through
00162    signal handlers work right.  Important are both the names
00163    (__restore and __restore_rt) and the exact instruction sequence.
00164    If you ever feel the need to make any changes, please notify the
00165    appropriate GDB maintainer.  */
00166 
00167 #define RESTORE(name, syscall) RESTORE2 (name, syscall)
00168 #define RESTORE2(name, syscall) \
00169 asm                                       \
00170   (                                       \
00171    ".text\n"                              \
00172    "   .align 16\n"                       \
00173    "__" #name ":\n"                       \
00174    "   movl $" #syscall ", %eax\n"        \
00175    "   int  $0x80"                        \
00176    );
00177 
00178 #ifdef __NR_rt_sigaction
00179 /* The return code for realtime-signals.  */
00180 RESTORE (restore_rt, __NR_rt_sigreturn)
00181 #endif
00182 
00183 /* For the boring old signals.  */
00184 #undef RESTORE2
00185 #define RESTORE2(name, syscall) \
00186 asm                                       \
00187   (                                       \
00188    ".text\n"                              \
00189    "   .align 8\n"                        \
00190    "__" #name ":\n"                       \
00191    "   popl %eax\n"                       \
00192    "   movl $" #syscall ", %eax\n"        \
00193    "   int  $0x80"                        \
00194    );
00195 
00196 RESTORE (restore, __NR_sigreturn)