1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#define INCL_DOSEXCEPTIONS /* for OS2 */ 18251875Speter#include "apr_arch_threadproc.h" 19251875Speter#include "apr_private.h" 20251875Speter#include "apr_pools.h" 21251875Speter#include "apr_signal.h" 22251875Speter#include "apr_strings.h" 23251875Speter 24251875Speter#include <assert.h> 25251875Speter#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H 26251875Speter#include <pthread.h> 27251875Speter#endif 28251875Speter 29251875Speter#ifdef SIGWAIT_TAKES_ONE_ARG 30251875Speter#define apr_sigwait(a,b) ((*(b)=sigwait((a)))<0?-1:0) 31251875Speter#else 32251875Speter#define apr_sigwait(a,b) sigwait((a),(b)) 33251875Speter#endif 34251875Speter 35251875SpeterAPR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum) 36251875Speter{ 37251875Speter#ifdef OS2 38251875Speter /* SIGTERM's don't work too well in OS/2 (only affects other EMX 39251875Speter * programs). CGIs may not be, esp. REXX scripts, so use a native 40251875Speter * call instead 41251875Speter */ 42251875Speter if (signum == SIGTERM) { 43251875Speter return APR_OS2_STATUS(DosSendSignalException(proc->pid, 44251875Speter XCPT_SIGNAL_BREAK)); 45251875Speter } 46251875Speter#endif /* OS2 */ 47251875Speter 48251875Speter if (kill(proc->pid, signum) == -1) { 49251875Speter return errno; 50251875Speter } 51251875Speter 52251875Speter return APR_SUCCESS; 53251875Speter} 54251875Speter 55251875Speter 56251875Speter#if APR_HAVE_SIGACTION 57251875Speter 58251875Speter#if defined(__NetBSD__) || defined(DARWIN) 59251875Speterstatic void avoid_zombies(int signo) 60251875Speter{ 61251875Speter int exit_status; 62251875Speter 63251875Speter while (waitpid(-1, &exit_status, WNOHANG) > 0) { 64251875Speter /* do nothing */ 65251875Speter } 66251875Speter} 67251875Speter#endif /* DARWIN */ 68251875Speter 69251875Speter/* 70251875Speter * Replace standard signal() with the more reliable sigaction equivalent 71251875Speter * from W. Richard Stevens' "Advanced Programming in the UNIX Environment" 72251875Speter * (the version that does not automatically restart system calls). 73251875Speter */ 74251875SpeterAPR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func) 75251875Speter{ 76251875Speter struct sigaction act, oact; 77251875Speter 78251875Speter act.sa_handler = func; 79251875Speter sigemptyset(&act.sa_mask); 80251875Speter act.sa_flags = 0; 81251875Speter#ifdef SA_INTERRUPT /* SunOS */ 82251875Speter act.sa_flags |= SA_INTERRUPT; 83251875Speter#endif 84251875Speter#if defined(__osf__) && defined(__alpha) 85251875Speter /* XXX jeff thinks this should be enabled whenever SA_NOCLDWAIT is defined */ 86251875Speter 87251875Speter /* this is required on Tru64 to cause child processes to 88251875Speter * disappear gracefully - XPG4 compatible 89251875Speter */ 90251875Speter if ((signo == SIGCHLD) && (func == SIG_IGN)) { 91251875Speter act.sa_flags |= SA_NOCLDWAIT; 92251875Speter } 93251875Speter#endif 94251875Speter#if defined(__NetBSD__) || defined(DARWIN) 95251875Speter /* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies, 96251875Speter * and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in 97251875Speter * the handler to avoid zombies 98251875Speter */ 99251875Speter if ((signo == SIGCHLD) && (func == SIG_IGN)) { 100251875Speter act.sa_handler = avoid_zombies; 101251875Speter } 102251875Speter#endif 103251875Speter if (sigaction(signo, &act, &oact) < 0) 104251875Speter return SIG_ERR; 105251875Speter return oact.sa_handler; 106251875Speter} 107251875Speter 108251875Speter#endif /* HAVE_SIGACTION */ 109251875Speter 110251875Speter/* AC_DECL_SYS_SIGLIST defines either of these symbols depending 111251875Speter * on the version of autoconf used. */ 112251875Speter#if defined(SYS_SIGLIST_DECLARED) || HAVE_DECL_SYS_SIGLIST 113251875Speter 114251875Spetervoid apr_signal_init(apr_pool_t *pglobal) 115251875Speter{ 116251875Speter} 117251875Speterconst char *apr_signal_description_get(int signum) 118251875Speter{ 119251875Speter return (signum >= 0) ? sys_siglist[signum] : "unknown signal (number)"; 120251875Speter} 121251875Speter 122251875Speter#else /* !(SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST) */ 123251875Speter 124251875Speter/* we need to roll our own signal description stuff */ 125251875Speter 126251875Speter#if defined(NSIG) 127251875Speter#define APR_NUMSIG NSIG 128251875Speter#elif defined(_NSIG) 129251875Speter#define APR_NUMSIG _NSIG 130251875Speter#elif defined(__NSIG) 131251875Speter#define APR_NUMSIG __NSIG 132251875Speter#else 133251875Speter#define APR_NUMSIG 33 /* breaks on OS/390 with < 33; 32 is o.k. for most */ 134251875Speter#endif 135251875Speter 136251875Speterstatic const char *signal_description[APR_NUMSIG]; 137251875Speter 138251875Speter#define store_desc(index, string) \ 139251875Speter do { \ 140251875Speter if (index >= APR_NUMSIG) { \ 141251875Speter assert(index < APR_NUMSIG); \ 142251875Speter } \ 143251875Speter else { \ 144251875Speter signal_description[index] = string; \ 145251875Speter } \ 146251875Speter } while (0) 147251875Speter 148251875Spetervoid apr_signal_init(apr_pool_t *pglobal) 149251875Speter{ 150251875Speter int sig; 151251875Speter 152251875Speter store_desc(0, "Signal 0"); 153251875Speter 154251875Speter#ifdef SIGHUP 155251875Speter store_desc(SIGHUP, "Hangup"); 156251875Speter#endif 157251875Speter#ifdef SIGINT 158251875Speter store_desc(SIGINT, "Interrupt"); 159251875Speter#endif 160251875Speter#ifdef SIGQUIT 161251875Speter store_desc(SIGQUIT, "Quit"); 162251875Speter#endif 163251875Speter#ifdef SIGILL 164251875Speter store_desc(SIGILL, "Illegal instruction"); 165251875Speter#endif 166251875Speter#ifdef SIGTRAP 167251875Speter store_desc(SIGTRAP, "Trace/BPT trap"); 168251875Speter#endif 169251875Speter#ifdef SIGIOT 170251875Speter store_desc(SIGIOT, "IOT instruction"); 171251875Speter#endif 172251875Speter#ifdef SIGABRT 173251875Speter store_desc(SIGABRT, "Abort"); 174251875Speter#endif 175251875Speter#ifdef SIGEMT 176251875Speter store_desc(SIGEMT, "Emulator trap"); 177251875Speter#endif 178251875Speter#ifdef SIGFPE 179251875Speter store_desc(SIGFPE, "Arithmetic exception"); 180251875Speter#endif 181251875Speter#ifdef SIGKILL 182251875Speter store_desc(SIGKILL, "Killed"); 183251875Speter#endif 184251875Speter#ifdef SIGBUS 185251875Speter store_desc(SIGBUS, "Bus error"); 186251875Speter#endif 187251875Speter#ifdef SIGSEGV 188251875Speter store_desc(SIGSEGV, "Segmentation fault"); 189251875Speter#endif 190251875Speter#ifdef SIGSYS 191251875Speter store_desc(SIGSYS, "Bad system call"); 192251875Speter#endif 193251875Speter#ifdef SIGPIPE 194251875Speter store_desc(SIGPIPE, "Broken pipe"); 195251875Speter#endif 196251875Speter#ifdef SIGALRM 197251875Speter store_desc(SIGALRM, "Alarm clock"); 198251875Speter#endif 199251875Speter#ifdef SIGTERM 200251875Speter store_desc(SIGTERM, "Terminated"); 201251875Speter#endif 202251875Speter#ifdef SIGUSR1 203251875Speter store_desc(SIGUSR1, "User defined signal 1"); 204251875Speter#endif 205251875Speter#ifdef SIGUSR2 206251875Speter store_desc(SIGUSR2, "User defined signal 2"); 207251875Speter#endif 208251875Speter#ifdef SIGCLD 209251875Speter store_desc(SIGCLD, "Child status change"); 210251875Speter#endif 211251875Speter#ifdef SIGCHLD 212251875Speter store_desc(SIGCHLD, "Child status change"); 213251875Speter#endif 214251875Speter#ifdef SIGPWR 215251875Speter store_desc(SIGPWR, "Power-fail restart"); 216251875Speter#endif 217251875Speter#ifdef SIGWINCH 218251875Speter store_desc(SIGWINCH, "Window changed"); 219251875Speter#endif 220251875Speter#ifdef SIGURG 221251875Speter store_desc(SIGURG, "urgent socket condition"); 222251875Speter#endif 223251875Speter#ifdef SIGPOLL 224251875Speter store_desc(SIGPOLL, "Pollable event occurred"); 225251875Speter#endif 226251875Speter#ifdef SIGIO 227251875Speter store_desc(SIGIO, "socket I/O possible"); 228251875Speter#endif 229251875Speter#ifdef SIGSTOP 230251875Speter store_desc(SIGSTOP, "Stopped (signal)"); 231251875Speter#endif 232251875Speter#ifdef SIGTSTP 233251875Speter store_desc(SIGTSTP, "Stopped"); 234251875Speter#endif 235251875Speter#ifdef SIGCONT 236251875Speter store_desc(SIGCONT, "Continued"); 237251875Speter#endif 238251875Speter#ifdef SIGTTIN 239251875Speter store_desc(SIGTTIN, "Stopped (tty input)"); 240251875Speter#endif 241251875Speter#ifdef SIGTTOU 242251875Speter store_desc(SIGTTOU, "Stopped (tty output)"); 243251875Speter#endif 244251875Speter#ifdef SIGVTALRM 245251875Speter store_desc(SIGVTALRM, "virtual timer expired"); 246251875Speter#endif 247251875Speter#ifdef SIGPROF 248251875Speter store_desc(SIGPROF, "profiling timer expired"); 249251875Speter#endif 250251875Speter#ifdef SIGXCPU 251251875Speter store_desc(SIGXCPU, "exceeded cpu limit"); 252251875Speter#endif 253251875Speter#ifdef SIGXFSZ 254251875Speter store_desc(SIGXFSZ, "exceeded file size limit"); 255251875Speter#endif 256251875Speter 257251875Speter for (sig = 0; sig < APR_NUMSIG; ++sig) 258251875Speter if (signal_description[sig] == NULL) 259251875Speter signal_description[sig] = apr_psprintf(pglobal, "signal #%d", sig); 260251875Speter} 261251875Speter 262251875Speterconst char *apr_signal_description_get(int signum) 263251875Speter{ 264251875Speter return 265251875Speter (signum >= 0 && signum < APR_NUMSIG) 266251875Speter ? signal_description[signum] 267251875Speter : "unknown signal (number)"; 268251875Speter} 269251875Speter 270251875Speter#endif /* SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST */ 271251875Speter 272251875Speter#if APR_HAS_THREADS && (HAVE_SIGSUSPEND || APR_HAVE_SIGWAIT) && !defined(OS2) 273251875Speter 274251875Speterstatic void remove_sync_sigs(sigset_t *sig_mask) 275251875Speter{ 276251875Speter#ifdef SIGABRT 277251875Speter sigdelset(sig_mask, SIGABRT); 278251875Speter#endif 279251875Speter#ifdef SIGBUS 280251875Speter sigdelset(sig_mask, SIGBUS); 281251875Speter#endif 282251875Speter#ifdef SIGEMT 283251875Speter sigdelset(sig_mask, SIGEMT); 284251875Speter#endif 285251875Speter#ifdef SIGFPE 286251875Speter sigdelset(sig_mask, SIGFPE); 287251875Speter#endif 288251875Speter#ifdef SIGILL 289251875Speter sigdelset(sig_mask, SIGILL); 290251875Speter#endif 291251875Speter#ifdef SIGIOT 292251875Speter sigdelset(sig_mask, SIGIOT); 293251875Speter#endif 294251875Speter#ifdef SIGPIPE 295251875Speter sigdelset(sig_mask, SIGPIPE); 296251875Speter#endif 297251875Speter#ifdef SIGSEGV 298251875Speter sigdelset(sig_mask, SIGSEGV); 299251875Speter#endif 300251875Speter#ifdef SIGSYS 301251875Speter sigdelset(sig_mask, SIGSYS); 302251875Speter#endif 303251875Speter#ifdef SIGTRAP 304251875Speter sigdelset(sig_mask, SIGTRAP); 305251875Speter#endif 306251875Speter 307251875Speter/* the rest of the signals removed from the mask in this function 308251875Speter * absolutely must be removed; you cannot block synchronous signals 309251875Speter * (requirement of pthreads API) 310251875Speter */ 311251875Speter} 312251875Speter 313251875SpeterAPR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum)) 314251875Speter{ 315251875Speter sigset_t sig_mask; 316251875Speter#if APR_HAVE_SIGWAIT 317251875Speter int (*sig_func)(int signum) = (int (*)(int))signal_handler; 318251875Speter#endif 319251875Speter 320251875Speter /* This thread will be the one responsible for handling signals */ 321251875Speter sigfillset(&sig_mask); 322251875Speter 323251875Speter /* On certain platforms, sigwait() returns EINVAL if any of various 324251875Speter * unblockable signals are included in the mask. This was first 325251875Speter * observed on AIX and Tru64. 326251875Speter */ 327251875Speter#ifdef SIGKILL 328251875Speter sigdelset(&sig_mask, SIGKILL); 329251875Speter#endif 330251875Speter#ifdef SIGSTOP 331251875Speter sigdelset(&sig_mask, SIGSTOP); 332251875Speter#endif 333251875Speter#ifdef SIGCONT 334251875Speter sigdelset(&sig_mask, SIGCONT); 335251875Speter#endif 336251875Speter#ifdef SIGWAITING 337251875Speter sigdelset(&sig_mask, SIGWAITING); 338251875Speter#endif 339251875Speter 340251875Speter /* no synchronous signals should be in the mask passed to sigwait() */ 341251875Speter remove_sync_sigs(&sig_mask); 342251875Speter 343251875Speter /* On AIX (4.3.3, at least), sigwait() won't wake up if the high- 344251875Speter * order bit of the second word of flags is turned on. sigdelset() 345251875Speter * returns an error when trying to turn this off, so we'll turn it 346251875Speter * off manually. 347251875Speter * 348251875Speter * Note that the private fields differ between 32-bit and 64-bit 349251875Speter * and even between _ALL_SOURCE and !_ALL_SOURCE. Except that on 350251875Speter * AIX 4.3 32-bit builds and 64-bit builds use the same definition. 351251875Speter * 352251875Speter * Applicable AIX fixes such that this is no longer needed: 353251875Speter * 354251875Speter * APAR IY23096 for AIX 51B, fix included in AIX 51C, and 355251875Speter * APAR IY24162 for 43X. 356251875Speter */ 357251875Speter#if defined(_AIX) 358251875Speter#if defined(__64BIT__) && defined(_AIXVERSION_510) 359251875Speter#ifdef _ALL_SOURCE 360251875Speter sig_mask.ss_set[3] &= 0x7FFFFFFF; 361251875Speter#else /* not _ALL_SOURCE */ 362251875Speter sig_mask.__ss_set[3] &= 0x7FFFFFFF; 363251875Speter#endif 364251875Speter#else /* not 64-bit build, or 64-bit build on 4.3 */ 365251875Speter#ifdef _ALL_SOURCE 366251875Speter sig_mask.hisigs &= 0x7FFFFFFF; 367251875Speter#else /* not _ALL_SOURCE */ 368251875Speter sig_mask.__hisigs &= 0x7FFFFFFF; 369251875Speter#endif 370251875Speter#endif 371251875Speter#endif /* _AIX */ 372251875Speter 373251875Speter while (1) { 374251875Speter#if APR_HAVE_SIGWAIT 375251875Speter int signal_received; 376251875Speter 377251875Speter if (apr_sigwait(&sig_mask, &signal_received) != 0) 378251875Speter { 379251875Speter /* handle sigwait() error here */ 380251875Speter } 381251875Speter 382251875Speter if (sig_func(signal_received) == 1) { 383251875Speter return APR_SUCCESS; 384251875Speter } 385251875Speter#elif HAVE_SIGSUSPEND 386251875Speter sigsuspend(&sig_mask); 387251875Speter#else 388251875Speter#error No apr_sigwait() and no sigsuspend() 389251875Speter#endif 390251875Speter } 391251875Speter} 392251875Speter 393251875SpeterAPR_DECLARE(apr_status_t) apr_setup_signal_thread(void) 394251875Speter{ 395251875Speter sigset_t sig_mask; 396251875Speter int rv; 397251875Speter 398251875Speter /* All threads should mask out signals to be handled by 399251875Speter * the thread doing sigwait(). 400251875Speter * 401251875Speter * No thread should ever block synchronous signals. 402251875Speter * See the Solaris man page for pthread_sigmask() for 403251875Speter * some information. Solaris chooses to knock out such 404251875Speter * processes when a blocked synchronous signal is 405251875Speter * delivered, skipping any registered signal handler. 406251875Speter * AIX doesn't call a signal handler either. At least 407251875Speter * one level of linux+glibc does call the handler even 408251875Speter * when the synchronous signal is blocked. 409251875Speter */ 410251875Speter sigfillset(&sig_mask); 411251875Speter remove_sync_sigs(&sig_mask); 412251875Speter 413251875Speter#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS 414251875Speter if ((rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL)) != 0) { 415251875Speter rv = errno; 416251875Speter } 417251875Speter#else 418251875Speter if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) { 419251875Speter#ifdef HAVE_ZOS_PTHREADS 420251875Speter rv = errno; 421251875Speter#endif 422251875Speter } 423251875Speter#endif 424251875Speter return rv; 425251875Speter} 426251875Speter 427251875Speter#endif /* APR_HAS_THREADS && ... */ 428251875Speter 429251875SpeterAPR_DECLARE(apr_status_t) apr_signal_block(int signum) 430251875Speter{ 431251875Speter#if APR_HAVE_SIGACTION 432251875Speter sigset_t sig_mask; 433251875Speter int rv; 434251875Speter 435251875Speter sigemptyset(&sig_mask); 436251875Speter 437251875Speter sigaddset(&sig_mask, signum); 438251875Speter 439251875Speter#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS 440251875Speter if ((rv = sigprocmask(SIG_BLOCK, &sig_mask, NULL)) != 0) { 441251875Speter rv = errno; 442251875Speter } 443251875Speter#else 444251875Speter if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0) { 445251875Speter#ifdef HAVE_ZOS_PTHREADS 446251875Speter rv = errno; 447251875Speter#endif 448251875Speter } 449251875Speter#endif 450251875Speter return rv; 451251875Speter#else 452251875Speter return APR_ENOTIMPL; 453251875Speter#endif 454251875Speter} 455251875Speter 456251875SpeterAPR_DECLARE(apr_status_t) apr_signal_unblock(int signum) 457251875Speter{ 458251875Speter#if APR_HAVE_SIGACTION 459251875Speter sigset_t sig_mask; 460251875Speter int rv; 461251875Speter 462251875Speter sigemptyset(&sig_mask); 463251875Speter 464251875Speter sigaddset(&sig_mask, signum); 465251875Speter 466251875Speter#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS 467251875Speter if ((rv = sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) { 468251875Speter rv = errno; 469251875Speter } 470251875Speter#else 471251875Speter if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) { 472251875Speter#ifdef HAVE_ZOS_PTHREADS 473251875Speter rv = errno; 474251875Speter#endif 475251875Speter } 476251875Speter#endif 477251875Speter return rv; 478251875Speter#else 479251875Speter return APR_ENOTIMPL; 480251875Speter#endif 481251875Speter} 482