LCOV - code coverage report
Current view: top level - src - npth-sigev.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 36 0.0 %
Date: 2016-09-12 12:52:07 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /* npth-sigev.c - signal handling interface
       2             :    Copyright (C) 2011 g10 Code GmbH
       3             : 
       4             :    This file is part of NPTH.
       5             : 
       6             :    NPTH is free software; you can redistribute it and/or modify it
       7             :    under the terms of either
       8             : 
       9             :    - the GNU Lesser General Public License as published by the Free
      10             :    Software Foundation; either version 3 of the License, or (at
      11             :    your option) any later version.
      12             : 
      13             :    or
      14             : 
      15             :    - the GNU General Public License as published by the Free
      16             :    Software Foundation; either version 2 of the License, or (at
      17             :    your option) any later version.
      18             : 
      19             :    or both in parallel, as here.
      20             : 
      21             :    NPTH is distributed in the hope that it will be useful, but WITHOUT
      22             :    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      23             :    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      24             :    License for more details.
      25             : 
      26             :    You should have received a copies of the GNU General Public License
      27             :    and the GNU Lesser General Public License along with this program;
      28             :    if not, see <http://www.gnu.org/licenses/>.  */
      29             : 
      30             : /* This is a support interface to make it easier to handle signals.
      31             : 
      32             :    The interfaces here support one (and only one) thread (here called
      33             :    "main thread") in the application to monitor several signals while
      34             :    selecting on filedescriptors.
      35             : 
      36             :    First, the main thread should call npth_sigev_init.  This
      37             :    initializes some global data structures used to record interesting
      38             :    and pending signals.
      39             : 
      40             :    Then, the main thread should call npth_sigev_add for every signal
      41             :    it is interested in observing, and finally npth_sigev_fini.  This
      42             :    will block the signal in the main threads sigmask.  Note that these
      43             :    signals should also be blocked in all other threads.  Since they
      44             :    are blocked in the main thread after calling npth_sigev_add, it is
      45             :    recommended to call npth_sigev_add in the main thread before
      46             :    creating any threads.
      47             : 
      48             :    The function npth_sigev_sigmask is a convenient function that
      49             :    returns the sigmask of the thread at time of npth_sigev_init, but
      50             :    with all registered signals unblocked.  It is recommended to do all
      51             :    other changes to the main thread's sigmask before calling
      52             :    npth_sigev_init, so that the return value of npth_sigev_sigmask can
      53             :    be used in the npth_pselect invocation.
      54             : 
      55             :    In any case, the main thread should invoke npth_pselect with a
      56             :    sigmask that has all signals that should be monitored unblocked.
      57             : 
      58             :    After npth_pselect returns, npth_sigev_get_pending can be called in
      59             :    a loop until it returns 0 to iterate over the list of pending
      60             :    signals.  Each time a signal is returned by that function, its
      61             :    status is reset to non-pending.  */
      62             : 
      63             : #ifdef HAVE_CONFIG_H
      64             : #include <config.h>
      65             : #endif
      66             : 
      67             : #include <signal.h>
      68             : #include <assert.h>
      69             : 
      70             : #include "npth.h"
      71             : 
      72             : /* Record events that have been noticed.  */
      73             : static sigset_t sigev_pending;
      74             : 
      75             : /* The signal mask during normal operation.  */
      76             : static sigset_t sigev_block;
      77             : 
      78             : /* The signal mask during pselect.  */
      79             : static sigset_t sigev_unblock;
      80             : 
      81             : /* Registered signal numbers.  Needed to iterate over sigset_t.
      82             :    Bah.  */
      83             : #define SIGEV_MAX 32
      84             : static int sigev_signum[SIGEV_MAX];
      85             : static int sigev_signum_cnt;
      86             : 
      87             : /* The internal handler which just sets a global flag.  */
      88             : static void
      89           0 : _sigev_handler (int signum)
      90             : {
      91           0 :   sigaddset (&sigev_pending, signum);
      92           0 : }
      93             : 
      94             : 
      95             : /* Start setting up signal event handling.  */
      96             : void
      97           0 : npth_sigev_init (void)
      98             : {
      99           0 :   sigemptyset (&sigev_pending);
     100           0 :   pthread_sigmask (SIG_SETMASK, NULL, &sigev_block);
     101           0 :   pthread_sigmask (SIG_SETMASK, NULL, &sigev_unblock);
     102           0 : }
     103             : 
     104             : 
     105             : /* Add signal SIGNUM to the list of watched signals.  */
     106             : void
     107           0 : npth_sigev_add (int signum)
     108             : {
     109             :   struct sigaction sa;
     110             :   sigset_t ss;
     111             : 
     112           0 :   sigemptyset(&ss);
     113             : 
     114           0 :   assert (sigev_signum_cnt < SIGEV_MAX);
     115           0 :   sigev_signum[sigev_signum_cnt++] = signum;
     116             : 
     117             :   /* Make sure we can receive it.  */
     118           0 :   sigdelset (&sigev_unblock, signum);
     119           0 :   sigaddset (&sigev_block, signum);
     120             : 
     121           0 :   sa.sa_handler = _sigev_handler;
     122           0 :   sa.sa_mask = ss;
     123           0 :   sa.sa_flags = 0; /* NOT setting SA_RESTART! */
     124             : 
     125           0 :   sigaction (signum, &sa, NULL);
     126           0 : }
     127             : 
     128             : 
     129             : #ifdef HAVE_PTHREAD_ATFORK
     130             : /* There is non-POSIX operating system where fork is not available to
     131             :    applications.  There, we have no pthread_atfork either.  In such a
     132             :    case, we don't call pthread_atfork.  */
     133             : static void
     134           0 : restore_sigmask_for_child_process (void)
     135             : {
     136           0 :   pthread_sigmask (SIG_SETMASK, &sigev_unblock, NULL);
     137           0 : }
     138             : #endif
     139             : 
     140             : /* Finish the list of watched signals.  This starts to block them,
     141             :    too.  */
     142             : void
     143           0 : npth_sigev_fini (void)
     144             : {
     145             :   /* Block the interesting signals.  */
     146           0 :   pthread_sigmask (SIG_SETMASK, &sigev_block, NULL);
     147             : #ifdef HAVE_PTHREAD_ATFORK
     148           0 :   pthread_atfork (NULL, NULL, restore_sigmask_for_child_process);
     149             : #endif
     150           0 : }
     151             : 
     152             : 
     153             : /* Get the sigmask as needed for pselect.  */
     154             : sigset_t *
     155           0 : npth_sigev_sigmask (void)
     156             : {
     157           0 :   return &sigev_unblock;
     158             : }
     159             : 
     160             : 
     161             : /* Return the next signal event that occured.  Returns if none are
     162             :    left, 1 on success.  */
     163             : int
     164           0 : npth_sigev_get_pending (int *r_signum)
     165             : {
     166             :   int i;
     167           0 :   for (i = 0; i < sigev_signum_cnt; i++)
     168             :     {
     169           0 :       int signum = sigev_signum[i];
     170           0 :       if (sigismember (&sigev_pending, signum))
     171             :         {
     172           0 :           sigdelset (&sigev_pending, signum);
     173           0 :           *r_signum = signum;
     174           0 :           return 1;
     175             :         }
     176             :     }
     177           0 :   return 0;
     178             : }
     179             : 

Generated by: LCOV version 1.11