From 988b0fdbc6f7f0ba06673b500dbab365bdcc3c4c Mon Sep 17 00:00:00 2001 From: mdw Date: Sat, 19 Jun 1999 20:33:16 +0000 Subject: [PATCH] More sophisticated and excessive signal and alarm handling. --- lock.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/lock.c b/lock.c index 445e43d..ad223ee 100644 --- a/lock.c +++ b/lock.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: lock.c,v 1.3 1999/06/06 01:23:00 mdw Exp $ + * $Id: lock.c,v 1.4 1999/06/19 20:33:16 mdw Exp $ * * Simplified POSIX locking interface * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: lock.c,v $ + * Revision 1.4 1999/06/19 20:33:16 mdw + * More sophisticated and excessive signal and alarm handling. + * * Revision 1.3 1999/06/06 01:23:00 mdw * Fix signal handling. * @@ -44,6 +47,7 @@ /*----- Header files ------------------------------------------------------*/ #include +#include #include #include #include @@ -60,9 +64,13 @@ #define LOCK_TIMEOUT 10 /* Maximum time in seconds to wait */ +/*----- Static variables --------------------------------------------------*/ + +static sigjmp_buf jmp; /* Jump here to interrup @fcntl@ */ + /*----- Main code ---------------------------------------------------------*/ -/* --- @lock_alarm@ --- * +/* --- @sigalrm@ --- * * * Arguments: @int sig@ = signal number * @@ -71,7 +79,7 @@ * Use: Makes sure that a @SIGALRM@ signal interrupts system calls. */ -static void lock_alarm(int sig) { ; } +static void sigalrm(int sig) { longjmp(jmp, 1); } /* --- @lock_file@ --- * * @@ -91,8 +99,10 @@ static void lock_alarm(int sig) { ; } int lock_file(int fd, unsigned how) { struct flock fk; - struct sigaction sa, oldsa; + struct sigaction sa, osa; + sigset_t ss, oss; int e; + int al, d, left; /* --- Fill in the easy bits --- */ @@ -118,26 +128,64 @@ int lock_file(int fd, unsigned how) return (-1); } - /* --- Set up the alarm --- */ + /* --- Block @SIGALRM@ for a while --- * + * + * I don't want stray alarms going off while I'm busy here. + */ + + sigemptyset(&ss); + sigaddset(&ss, SIGALRM); + if (sigprocmask(SIG_BLOCK, &ss, &oss)) + return (-1); + + /* --- Set up the signal handler --- */ - sa.sa_handler = lock_alarm; + sa.sa_handler = sigalrm; sa.sa_flags = 0; +#ifdef SA_INTERRUPT + sa.sa_flags |= SA_INTERRUPT; +#endif sigemptyset(&sa.sa_mask); - if (sigaction(SIGALRM, &sa, &oldsa)) + if (sigaction(SIGALRM, &sa, &osa)) return (-1); - /* --- Do it --- */ + /* --- Set up the alarm, remembering when it's meant to go off --- */ + + al = alarm(0); + if (al && al < LOCK_TIMEOUT) + d = al; + else + d = LOCK_TIMEOUT; + alarm(d); - alarm(LOCK_TIMEOUT); - if ((e = fcntl(fd, F_SETLKW, &fk)) != 0) { - if (errno == EINTR) - errno = EAGAIN; + /* --- Set up the return context for the signal handler --- */ + + if (setjmp(jmp)) { + sigprocmask(SIG_SETMASK, &oss, 0); + errno = EINTR; + e = -1; + goto done; + } + + /* --- Unblock the signal and we're ready --- */ + + if (sigprocmask(SIG_SETMASK, &oss, 0)) { + alarm(al); + e = -1; + goto done; } - /* --- Remove the alarm handling --- */ + /* --- Do it --- */ + + e = fcntl(fd, F_SETLKW, &fk); + + /* --- Tidy up the mess I left --- */ - alarm(0); - sigaction(SIGALRM, &oldsa, 0); + left = alarm(0); + if (al) + alarm(al - d + left); +done: + sigaction(SIGALRM, &osa, 0); return (e); } -- 2.11.0