X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/9f8886c72ce02c9c4487a562a24a518c96043664..e109873133d224df7973bceedae82172924cd69e:/sig.c diff --git a/sig.c b/sig.c index 1bfddbf..87dbb33 100644 --- a/sig.c +++ b/sig.c @@ -1,13 +1,11 @@ /* -*-c-*- - * - * $Id: sig.c,v 1.1 1999/07/26 23:16:26 mdw Exp $ * * Signal handling * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of the mLib utilities library. * @@ -15,26 +13,18 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * mLib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with mLib; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: sig.c,v $ - * Revision 1.1 1999/07/26 23:16:26 mdw - * Signal handling integrated into I/O system. - * - */ - /*----- Header files ------------------------------------------------------*/ #include @@ -63,6 +53,8 @@ typedef struct sigstate { static sel_file sigsel; static int sigfd; static sigstate *sigs; +static sigset_t ss_all, ss_caught; +static unsigned nsig; /*----- Main code ---------------------------------------------------------*/ @@ -72,14 +64,21 @@ static sigstate *sigs; * * Returns: --- * - * Use: Generic signal handler. Just writes a single byte to the - * signal pipe. The byte contains the signal number. + * Use: Generic signal handler. Writes a single byte to the + * signal pipe. The byte contains the signal number. Also + * sets the appropriate bit in @ss_caught@ to indicate which + * signals are pending. */ static void sig_handler(int n) { + int e = errno; unsigned char sch = (unsigned char)n; + sigprocmask(SIG_BLOCK, &ss_all, 0); + sigaddset(&ss_caught, n); write(sigfd, &sch, 1); + /* The system should reset the signal mask here. */ + errno = e; } /* --- @sig_read@ --- * @@ -96,27 +95,41 @@ static void sig_handler(int n) static void sig_read(int fd, unsigned mode, void *p) { sigset_t ss; - unsigned char buf[256]; - int r; - sigemptyset(&ss); - while ((r = read(fd, buf, sizeof(buf))) > 0) { - unsigned char *p, *q; - for (p = buf, q = buf + r; p < q; p++) { + /* --- Read the currently caught signals --- * + * + * Block signals while the mask is being copied. + */ + + { + sigset_t oss; + unsigned char buf[256]; + + sigprocmask(SIG_BLOCK, &ss_all, &oss); + ss = ss_caught; + sigemptyset(&ss_caught); + while (read(fd, buf, sizeof(buf)) > 0) + /* Do nothing */; + sigprocmask(SIG_SETMASK, &oss, 0); + } + + /* --- Process the caught signals --- */ + + { + int i; + for (i = 0; i < nsig; i++) { sig *s; - int n = *p; - if (sigismember(&ss, n)) + if (!sigismember(&ss, i)) continue; - sigaddset(&ss, n); - s = sigs[n].list; + s = sigs[i].list; while (s) { sig *ss = s; s = s->next; - ss->proc(n, ss->p); + ss->proc(i, ss->p); } } } -} +} /* --- @sig_add@ --- * * @@ -152,6 +165,7 @@ void sig_add(sig *s, int n, void (*proc)(int /*n*/, void */*p*/), void *p) sa.sa_flags |= SA_RESTART; #endif sigemptyset(&sa.sa_mask); + sigaddset(&ss_all, n); sigaction(n, &sa, &ss->sa); } @@ -186,8 +200,10 @@ void sig_remove(sig *s) /* --- Maybe remove the handler --- */ - if (!ss->list) + if (!ss->list) { sigaction(s->sig, &ss->sa, 0); + sigdelset(&ss_all, s->sig); + } } /* --- @sig_init@ --- * @@ -202,7 +218,6 @@ void sig_remove(sig *s) void sig_init(sel_state *s) { int fd[2]; - unsigned nsig; /* --- Work out how many signals there are --- */ @@ -261,10 +276,12 @@ void sig_init(sel_state *s) fdflags(fd[1], O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); /* --- Set everything up for the future --- */ - + sigfd = fd[1]; sel_initfile(s, &sigsel, fd[0], SEL_READ, sig_read, 0); sel_addfile(&sigsel); + sigemptyset(&ss_all); + sigemptyset(&ss_caught); } /*----- That's all, folks -------------------------------------------------*/