- alrm = signal(SIGALRM, lock_alarm);
- alarm(LOCK_TIMEOUT);
- if ((e = fcntl(fd, F_SETLKW, &fk)) != 0) {
- if (errno == EINTR)
- errno = EAGAIN;
+ /* --- 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 = sigalrm;
+ sa.sa_flags = 0;
+#ifdef SA_INTERRUPT
+ sa.sa_flags |= SA_INTERRUPT;
+#endif
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGALRM, &sa, &osa))
+ return (-1);
+
+ /* --- 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);
+
+ /* --- 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;