da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * signal critical region support
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sig.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int sig;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsignals[] = /* held inside critical region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGINT, SIG_REG_EXEC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGPIPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGPIPE, SIG_REG_EXEC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGQUIT
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGQUIT, SIG_REG_EXEC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGHUP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGHUP, SIG_REG_EXEC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD) && ( !defined(SIGCLD) || SIGCHLD != SIGCLD || _lib_sigprocmask || _lib_sigsetmask )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGCHLD, SIG_REG_PROC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGTSTP, SIG_REG_TERM,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTTIN
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGTTIN, SIG_REG_TERM,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTTOU
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIGTTOU, SIG_REG_TERM,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef SIG_SETMASK
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _lib_sigprocmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_lib_sigprocmask && !_lib_sigsetmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long hold; /* held signal mask */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * hold last signal for later delivery
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chininterrupt(int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(sig, interrupt);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hold |= sigmask(sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * critical signal region handler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * op>0 new region according to SIG_REG_*, return region level
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * op==0 pop region, return region level
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * op<0 return non-zero if any signals held in current region
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * signals[] held until region popped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsigcritical(int op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int region;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int level;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigprocmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static sigset_t mask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigset_t nmask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigsetmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static long mask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static Sig_handler_t handler[elementsof(signals)];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!level++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin region = op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op & SIG_REG_SET)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin level--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigprocmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigemptyset(&nmask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(signals); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op & signals[i].op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigaddset(&nmask, signals[i].sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigprocmask(SIG_BLOCK, &nmask, &mask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigsetmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mask = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(signals); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op & signals[i].op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mask |= sigmask(signals[i].sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mask = sigblock(mask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hold = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(signals); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((op & signals[i].op) && (handler[i] = signal(signals[i].sig, interrupt)) == SIG_IGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(signals[i].sig, handler[i]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hold &= ~sigmask(signals[i].sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return level;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (op < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigprocmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigpending(&nmask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(signals); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (region & signals[i].op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sigismember(&nmask, signals[i].sig))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigsetmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* no way to get pending signals without installing handler */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return hold != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * a vfork() may have intervened so we
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * allow apparent nesting mismatches
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (--level <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin level = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigprocmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigprocmask(SIG_SETMASK, &mask, NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigsetmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigsetmask(mask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(signals); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (region & signals[i].op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(signals[i].sig, handler[i]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (hold)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(signals); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (region & signals[i].op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (hold & sigmask(signals[i].sig))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin kill(getpid(), signals[i].sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pause();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return level;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}