summaryrefslogtreecommitdiff
path: root/sbin/dump/tape.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2005-01-23 18:33:13 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2005-01-23 18:33:13 +0000
commita8de16afff4ff24adefd1c8c4759688778f89fdd (patch)
tree2fa2009789587350113ec6e48c40f0f30c5adccd /sbin/dump/tape.c
parent48313549b28484b7b05675e02f19695265346b3a (diff)
Avoid signal race condition. If a slave gets SIGUSR2 between the
"setjmp" and the "ready = 1" statements, the slave will pause forever and the whole dump hangs. Fix by hannken@netbsd.org Closes PR 4070; also tested by henning@ and marc@
Diffstat (limited to 'sbin/dump/tape.c')
-rw-r--r--sbin/dump/tape.c35
1 files changed, 13 insertions, 22 deletions
diff --git a/sbin/dump/tape.c b/sbin/dump/tape.c
index a585faf6dc1..392c0afbe96 100644
--- a/sbin/dump/tape.c
+++ b/sbin/dump/tape.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tape.c,v 1.21 2004/11/04 20:10:07 deraadt Exp $ */
+/* $OpenBSD: tape.c,v 1.22 2005/01/23 18:33:12 millert Exp $ */
/* $NetBSD: tape.c,v 1.11 1997/06/05 11:13:26 lukem Exp $ */
/*-
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)tape.c 8.2 (Berkeley) 3/17/94";
#else
-static const char rcsid[] = "$OpenBSD: tape.c,v 1.21 2004/11/04 20:10:07 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: tape.c,v 1.22 2005/01/23 18:33:12 millert Exp $";
#endif
#endif /* not lint */
@@ -56,7 +56,6 @@ static const char rcsid[] = "$OpenBSD: tape.c,v 1.21 2004/11/04 20:10:07 deraadt
#include <errno.h>
#include <fcntl.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -121,10 +120,6 @@ static int tapea_volume; /* value of spcl.c_tapea at volume start */
int master; /* pid of master, for sending error signals */
int tenths; /* length of tape used per block written */
static int caught; /* have we caught the signal to proceed? */
-static int ready; /* have we reached the lock point without having */
- /* received the SIGUSR2 signal from the prev slave? */
-static jmp_buf jmpbuf; /* where to jump to if we are ready when the */
- /* SIGUSR2 arrives from the previous slave */
int
alloctape(void)
@@ -723,9 +718,6 @@ Exit(int status)
void
proceed(int signo)
{
-
- if (ready)
- longjmp(jmpbuf, 1);
caught++;
}
@@ -795,10 +787,8 @@ killall(void)
static void
doslave(int cmd, int slave_number)
{
- int nread;
- int nextslave, size, eot_count;
- volatile int wrote;
- sigset_t sigset;
+ int nread, nextslave, size, wrote, eot_count;
+ sigset_t nsigset, osigset;
/*
* Need our own seek pointer.
@@ -833,13 +823,14 @@ doslave(int cmd, int slave_number)
quit("master/slave protocol botched.\n");
}
}
- if (setjmp(jmpbuf) == 0) {
- ready = 1;
- if (!caught)
- (void) pause();
- }
- ready = 0;
+
+ sigemptyset(&nsigset);
+ sigaddset(&nsigset, SIGUSR2);
+ sigprocmask(SIG_BLOCK, &nsigset, &osigset);
+ while (!caught)
+ sigsuspend(&osigset);
caught = 0;
+ sigprocmask(SIG_SETMASK, &osigset, NULL);
/* Try to write the data... */
eot_count = 0;
@@ -883,9 +874,9 @@ doslave(int cmd, int slave_number)
if (size < 0) {
(void) kill(master, SIGUSR1);
- sigemptyset(&sigset);
+ sigemptyset(&nsigset);
for (;;)
- sigsuspend(&sigset);
+ sigsuspend(&nsigset);
} else {
/*
* pass size of write back to master