Back to index

glibc  2.9
sigaction.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2002, 2007
00002      Free Software Foundation, Inc.
00003 
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <errno.h>
00022 #include <signal.h>
00023 #include <hurd.h>
00024 #include <hurd/signal.h>
00025 
00026 /* If ACT is not NULL, change the action for SIG to *ACT.
00027    If OACT is not NULL, put the old action for SIG in *OACT.  */
00028 int
00029 __sigaction (sig, act, oact)
00030      int sig;
00031      const struct sigaction *act;
00032      struct sigaction *oact;
00033 {
00034   struct hurd_sigstate *ss;
00035   struct sigaction a, old;
00036   sigset_t pending;
00037 
00038   if (sig <= 0 || sig >= NSIG ||
00039       (act != NULL && act->sa_handler != SIG_DFL &&
00040        ((__sigmask (sig) & _SIG_CANT_MASK) ||
00041        act->sa_handler == SIG_ERR)))
00042     {
00043       errno = EINVAL;
00044       return -1;
00045     }
00046 
00047   /* Copy so we fault before taking locks.  */
00048   if (act != NULL)
00049     a = *act;
00050 
00051   ss = _hurd_self_sigstate ();
00052 
00053   __spin_lock (&ss->critical_section_lock);
00054   __spin_lock (&ss->lock);
00055   old = ss->actions[sig];
00056   if (act != NULL)
00057     ss->actions[sig] = a;
00058 
00059   if (act != NULL && sig == SIGCHLD &&
00060       (a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP))
00061     {
00062       __spin_unlock (&ss->lock);
00063 
00064       /* Inform the proc server whether or not it should send us SIGCHLD for
00065         stopped children.  We do this in a critical section so that no
00066         SIGCHLD can arrive in the middle and be of indeterminate status.  */
00067       __USEPORT (PROC,
00068                __proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
00069 
00070       __spin_lock (&ss->lock);
00071       pending = ss->pending & ~ss->blocked;
00072     }
00073   else if (act != NULL && (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL))
00074     /* We are changing to an action that might be to ignore SIG signals.
00075        If SIG is blocked and pending and the new action is to ignore it, we
00076        must remove it from the pending set now; if the action is changed
00077        back and then SIG is unblocked, the signal pending now should not
00078        arrive.  So wake up the signal thread to check the new state and do
00079        the right thing.  */
00080     pending = ss->pending & __sigmask (sig);
00081   else
00082     pending = 0;
00083 
00084   __spin_unlock (&ss->lock);
00085   __spin_unlock (&ss->critical_section_lock);
00086 
00087   if (pending)
00088     __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
00089 
00090   if (oact != NULL)
00091     *oact = old;
00092 
00093   return 0;
00094 }
00095 libc_hidden_def (__sigaction)
00096 weak_alias (__sigaction, sigaction)