"Fossies" - the Fresh Open Source Software Archive

Member "apr-1.7.0/threadproc/unix/signals.c" (7 Mar 2019, 12298 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "signals.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.6.5_vs_1.7.0.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 #define INCL_DOSEXCEPTIONS      /* for OS2 */
   18 #include "apr_arch_threadproc.h"
   19 #include "apr_private.h"
   20 #include "apr_pools.h"
   21 #include "apr_signal.h"
   22 #include "apr_strings.h"
   23 
   24 #include <assert.h>
   25 #if APR_HAS_THREADS && APR_HAVE_PTHREAD_H
   26 #include <pthread.h>
   27 #endif
   28 
   29 #ifdef SIGWAIT_TAKES_ONE_ARG
   30 #define apr_sigwait(a,b) ((*(b)=sigwait((a)))<0?-1:0)
   31 #else
   32 #define apr_sigwait(a,b) sigwait((a),(b))
   33 #endif
   34 
   35 APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum)
   36 {
   37 #ifdef OS2
   38     /* SIGTERM's don't work too well in OS/2 (only affects other EMX
   39      * programs). CGIs may not be, esp. REXX scripts, so use a native
   40      * call instead
   41      */
   42     if (signum == SIGTERM) {
   43         return APR_OS2_STATUS(DosSendSignalException(proc->pid,
   44                                                      XCPT_SIGNAL_BREAK));
   45     }
   46 #endif /* OS2 */
   47 
   48     if (kill(proc->pid, signum) == -1) {
   49         return errno;
   50     }
   51 
   52     return APR_SUCCESS;
   53 }
   54 
   55 
   56 #if APR_HAVE_SIGACTION
   57 
   58 #if defined(__NetBSD__) || defined(DARWIN)
   59 static void avoid_zombies(int signo)
   60 {
   61     int exit_status;
   62 
   63     while (waitpid(-1, &exit_status, WNOHANG) > 0) {
   64         /* do nothing */
   65     }
   66 }
   67 #endif /* DARWIN */
   68 
   69 /*
   70  * Replace standard signal() with the more reliable sigaction equivalent
   71  * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
   72  * (the version that does not automatically restart system calls).
   73  */
   74 APR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func)
   75 {
   76     struct sigaction act, oact;
   77 
   78     act.sa_handler = func;
   79     sigemptyset(&act.sa_mask);
   80     act.sa_flags = 0;
   81 #ifdef SA_INTERRUPT             /* SunOS */
   82     act.sa_flags |= SA_INTERRUPT;
   83 #endif
   84 #if defined(__osf__) && defined(__alpha)
   85     /* XXX jeff thinks this should be enabled whenever SA_NOCLDWAIT is defined */
   86 
   87     /* this is required on Tru64 to cause child processes to
   88      * disappear gracefully - XPG4 compatible 
   89      */
   90     if ((signo == SIGCHLD) && (func == SIG_IGN)) {
   91         act.sa_flags |= SA_NOCLDWAIT;
   92     }
   93 #endif
   94 #if defined(__NetBSD__) || defined(DARWIN)
   95     /* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies,
   96      * and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in 
   97      * the handler to avoid zombies
   98      */
   99     if ((signo == SIGCHLD) && (func == SIG_IGN)) {
  100         act.sa_handler = avoid_zombies;
  101     }
  102 #endif
  103     if (sigaction(signo, &act, &oact) < 0)
  104         return SIG_ERR;
  105     return oact.sa_handler;
  106 }
  107 
  108 #endif /* HAVE_SIGACTION */
  109 
  110 /* AC_DECL_SYS_SIGLIST defines either of these symbols depending
  111  * on the version of autoconf used. */
  112 #if defined(SYS_SIGLIST_DECLARED) || HAVE_DECL_SYS_SIGLIST
  113 
  114 void apr_signal_init(apr_pool_t *pglobal)
  115 {
  116 }
  117 const char *apr_signal_description_get(int signum)
  118 {
  119     return (signum >= 0) ? sys_siglist[signum] : "unknown signal (number)";
  120 }
  121 
  122 #else /* !(SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST) */
  123 
  124 /* we need to roll our own signal description stuff */
  125 
  126 #if defined(NSIG)
  127 #define APR_NUMSIG NSIG
  128 #elif defined(_NSIG)
  129 #define APR_NUMSIG _NSIG
  130 #elif defined(__NSIG)
  131 #define APR_NUMSIG __NSIG
  132 #else
  133 #define APR_NUMSIG 33   /* breaks on OS/390 with < 33; 32 is o.k. for most */
  134 #endif
  135 
  136 static const char *signal_description[APR_NUMSIG];
  137 
  138 #define store_desc(index, string) \
  139         do { \
  140             if (index >= APR_NUMSIG) { \
  141                 assert(index < APR_NUMSIG); \
  142             } \
  143             else { \
  144                 signal_description[index] = string; \
  145             } \
  146         } while (0)
  147 
  148 void apr_signal_init(apr_pool_t *pglobal)
  149 {
  150     int sig;
  151 
  152     store_desc(0, "Signal 0");
  153 
  154 #ifdef SIGHUP
  155     store_desc(SIGHUP, "Hangup");
  156 #endif
  157 #ifdef SIGINT
  158     store_desc(SIGINT, "Interrupt");
  159 #endif
  160 #ifdef SIGQUIT
  161     store_desc(SIGQUIT, "Quit");
  162 #endif
  163 #ifdef SIGILL
  164     store_desc(SIGILL, "Illegal instruction");
  165 #endif
  166 #ifdef SIGTRAP
  167     store_desc(SIGTRAP, "Trace/BPT trap");
  168 #endif
  169 #ifdef SIGIOT
  170     store_desc(SIGIOT, "IOT instruction");
  171 #endif
  172 #ifdef SIGABRT
  173     store_desc(SIGABRT, "Abort");
  174 #endif
  175 #ifdef SIGEMT
  176     store_desc(SIGEMT, "Emulator trap");
  177 #endif
  178 #ifdef SIGFPE
  179     store_desc(SIGFPE, "Arithmetic exception");
  180 #endif
  181 #ifdef SIGKILL
  182     store_desc(SIGKILL, "Killed");
  183 #endif
  184 #ifdef SIGBUS
  185     store_desc(SIGBUS, "Bus error");
  186 #endif
  187 #ifdef SIGSEGV
  188     store_desc(SIGSEGV, "Segmentation fault");
  189 #endif
  190 #ifdef SIGSYS
  191     store_desc(SIGSYS, "Bad system call");
  192 #endif
  193 #ifdef SIGPIPE
  194     store_desc(SIGPIPE, "Broken pipe");
  195 #endif
  196 #ifdef SIGALRM
  197     store_desc(SIGALRM, "Alarm clock");
  198 #endif
  199 #ifdef SIGTERM
  200     store_desc(SIGTERM, "Terminated");
  201 #endif
  202 #ifdef SIGUSR1
  203     store_desc(SIGUSR1, "User defined signal 1");
  204 #endif
  205 #ifdef SIGUSR2
  206     store_desc(SIGUSR2, "User defined signal 2");
  207 #endif
  208 #ifdef SIGCLD
  209     store_desc(SIGCLD, "Child status change");
  210 #endif
  211 #ifdef SIGCHLD
  212     store_desc(SIGCHLD, "Child status change");
  213 #endif
  214 #ifdef SIGPWR
  215     store_desc(SIGPWR, "Power-fail restart");
  216 #endif
  217 #ifdef SIGWINCH
  218     store_desc(SIGWINCH, "Window changed");
  219 #endif
  220 #ifdef SIGURG
  221     store_desc(SIGURG, "urgent socket condition");
  222 #endif
  223 #ifdef SIGPOLL
  224     store_desc(SIGPOLL, "Pollable event occurred");
  225 #endif
  226 #ifdef SIGIO
  227     store_desc(SIGIO, "socket I/O possible");
  228 #endif
  229 #ifdef SIGSTOP
  230     store_desc(SIGSTOP, "Stopped (signal)");
  231 #endif
  232 #ifdef SIGTSTP
  233     store_desc(SIGTSTP, "Stopped");
  234 #endif
  235 #ifdef SIGCONT
  236     store_desc(SIGCONT, "Continued");
  237 #endif
  238 #ifdef SIGTTIN
  239     store_desc(SIGTTIN, "Stopped (tty input)");
  240 #endif
  241 #ifdef SIGTTOU
  242     store_desc(SIGTTOU, "Stopped (tty output)");
  243 #endif
  244 #ifdef SIGVTALRM
  245     store_desc(SIGVTALRM, "virtual timer expired");
  246 #endif
  247 #ifdef SIGPROF
  248     store_desc(SIGPROF, "profiling timer expired");
  249 #endif
  250 #ifdef SIGXCPU
  251     store_desc(SIGXCPU, "exceeded cpu limit");
  252 #endif
  253 #ifdef SIGXFSZ
  254     store_desc(SIGXFSZ, "exceeded file size limit");
  255 #endif
  256 
  257     for (sig = 0; sig < APR_NUMSIG; ++sig)
  258         if (signal_description[sig] == NULL)
  259             signal_description[sig] = apr_psprintf(pglobal, "signal #%d", sig);
  260 }
  261 
  262 const char *apr_signal_description_get(int signum)
  263 {
  264     return
  265         (signum >= 0 && signum < APR_NUMSIG)
  266         ? signal_description[signum]
  267         : "unknown signal (number)";
  268 }
  269 
  270 #endif /* SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST */
  271 
  272 #if APR_HAS_THREADS && (HAVE_SIGSUSPEND || APR_HAVE_SIGWAIT) && !defined(OS2)
  273 
  274 static void remove_sync_sigs(sigset_t *sig_mask)
  275 {
  276 #ifdef SIGABRT
  277     sigdelset(sig_mask, SIGABRT);
  278 #endif
  279 #ifdef SIGBUS
  280     sigdelset(sig_mask, SIGBUS);
  281 #endif
  282 #ifdef SIGEMT
  283     sigdelset(sig_mask, SIGEMT);
  284 #endif
  285 #ifdef SIGFPE
  286     sigdelset(sig_mask, SIGFPE);
  287 #endif
  288 #ifdef SIGILL
  289     sigdelset(sig_mask, SIGILL);
  290 #endif
  291 #ifdef SIGIOT
  292     sigdelset(sig_mask, SIGIOT);
  293 #endif
  294 #ifdef SIGPIPE
  295     sigdelset(sig_mask, SIGPIPE);
  296 #endif
  297 #ifdef SIGSEGV
  298     sigdelset(sig_mask, SIGSEGV);
  299 #endif
  300 #ifdef SIGSYS
  301     sigdelset(sig_mask, SIGSYS);
  302 #endif
  303 #ifdef SIGTRAP
  304     sigdelset(sig_mask, SIGTRAP);
  305 #endif
  306 
  307 /* the rest of the signals removed from the mask in this function
  308  * absolutely must be removed; you cannot block synchronous signals
  309  * (requirement of pthreads API)
  310  */
  311 }
  312 
  313 APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum))
  314 {
  315     sigset_t sig_mask;
  316 #if APR_HAVE_SIGWAIT
  317     int (*sig_func)(int signum) = (int (*)(int))signal_handler;
  318 #endif
  319 
  320     /* This thread will be the one responsible for handling signals */
  321     sigfillset(&sig_mask);
  322 
  323     /* On certain platforms, sigwait() returns EINVAL if any of various
  324      * unblockable signals are included in the mask.  This was first 
  325      * observed on AIX and Tru64.
  326      */
  327 #ifdef SIGKILL
  328     sigdelset(&sig_mask, SIGKILL);
  329 #endif
  330 #ifdef SIGSTOP
  331     sigdelset(&sig_mask, SIGSTOP);
  332 #endif
  333 #ifdef SIGCONT
  334     sigdelset(&sig_mask, SIGCONT);
  335 #endif
  336 #ifdef SIGWAITING
  337     sigdelset(&sig_mask, SIGWAITING);
  338 #endif
  339 
  340     /* no synchronous signals should be in the mask passed to sigwait() */
  341     remove_sync_sigs(&sig_mask);
  342 
  343     /* On AIX (4.3.3, at least), sigwait() won't wake up if the high-
  344      * order bit of the second word of flags is turned on.  sigdelset()
  345      * returns an error when trying to turn this off, so we'll turn it
  346      * off manually.
  347      *
  348      * Note that the private fields differ between 32-bit and 64-bit
  349      * and even between _ALL_SOURCE and !_ALL_SOURCE.  Except that on
  350      * AIX 4.3 32-bit builds and 64-bit builds use the same definition.
  351      *
  352      * Applicable AIX fixes such that this is no longer needed:
  353      *
  354      * APAR IY23096 for AIX 51B, fix included in AIX 51C, and
  355      * APAR IY24162 for 43X.
  356      */
  357 #if defined(_AIX)
  358 #if defined(__64BIT__) && defined(_AIXVERSION_510)
  359 #ifdef _ALL_SOURCE
  360         sig_mask.ss_set[3] &= 0x7FFFFFFF;
  361 #else /* not _ALL_SOURCE */
  362         sig_mask.__ss_set[3] &= 0x7FFFFFFF;
  363 #endif
  364 #else /* not 64-bit build, or 64-bit build on 4.3 */
  365 #ifdef _ALL_SOURCE
  366         sig_mask.hisigs &= 0x7FFFFFFF;
  367 #else /* not _ALL_SOURCE */
  368         sig_mask.__hisigs &= 0x7FFFFFFF;
  369 #endif
  370 #endif
  371 #endif /* _AIX */
  372 
  373     while (1) {
  374 #if APR_HAVE_SIGWAIT
  375         int signal_received;
  376 
  377         if (apr_sigwait(&sig_mask, &signal_received) != 0)
  378         {
  379             /* handle sigwait() error here */
  380         }
  381         
  382         if (sig_func(signal_received) == 1) {
  383             return APR_SUCCESS;
  384         }
  385 #elif HAVE_SIGSUSPEND
  386     sigsuspend(&sig_mask);
  387 #else
  388 #error No apr_sigwait() and no sigsuspend()
  389 #endif
  390     }
  391 }
  392 
  393 APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
  394 {
  395     sigset_t sig_mask;
  396     int rv;
  397 
  398     /* All threads should mask out signals to be handled by
  399      * the thread doing sigwait().
  400      *
  401      * No thread should ever block synchronous signals.
  402      * See the Solaris man page for pthread_sigmask() for
  403      * some information.  Solaris chooses to knock out such
  404      * processes when a blocked synchronous signal is 
  405      * delivered, skipping any registered signal handler.
  406      * AIX doesn't call a signal handler either.  At least
  407      * one level of linux+glibc does call the handler even
  408      * when the synchronous signal is blocked.
  409      */
  410     sigfillset(&sig_mask);
  411     remove_sync_sigs(&sig_mask);
  412 
  413 #if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
  414     if ((rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
  415         rv = errno;
  416     }
  417 #else
  418     if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
  419 #ifdef HAVE_ZOS_PTHREADS
  420         rv = errno;
  421 #endif
  422     }
  423 #endif
  424     return rv;
  425 }
  426 
  427 #endif /* APR_HAS_THREADS && ... */
  428 
  429 APR_DECLARE(apr_status_t) apr_signal_block(int signum)
  430 {
  431 #if APR_HAVE_SIGACTION
  432     sigset_t sig_mask;
  433     int rv;
  434 
  435     sigemptyset(&sig_mask);
  436 
  437     sigaddset(&sig_mask, signum);
  438 
  439 #if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
  440     if ((rv = sigprocmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
  441         rv = errno;
  442     }
  443 #else
  444     if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0) {
  445 #ifdef HAVE_ZOS_PTHREADS
  446         rv = errno;
  447 #endif
  448     }
  449 #endif
  450     return rv;
  451 #else
  452     return APR_ENOTIMPL;
  453 #endif
  454 }
  455 
  456 APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
  457 {
  458 #if APR_HAVE_SIGACTION
  459     sigset_t sig_mask;
  460     int rv;
  461 
  462     sigemptyset(&sig_mask);
  463 
  464     sigaddset(&sig_mask, signum);
  465 
  466 #if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS
  467     if ((rv = sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
  468         rv = errno;
  469     }
  470 #else
  471     if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
  472 #ifdef HAVE_ZOS_PTHREADS
  473         rv = errno;
  474 #endif
  475     }
  476 #endif
  477     return rv;
  478 #else
  479     return APR_ENOTIMPL;
  480 #endif
  481 }