diff options
Diffstat (limited to 'bin/dd/misc.c')
-rw-r--r-- | bin/dd/misc.c | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/bin/dd/misc.c b/bin/dd/misc.c index 405448eb1cb0..05c19b5b2073 100644 --- a/bin/dd/misc.c +++ b/bin/dd/misc.c @@ -33,14 +33,6 @@ * SUCH DAMAGE. */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/types.h> #include <err.h> @@ -48,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <inttypes.h> #include <libutil.h> #include <signal.h> +#include <stdatomic.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -147,11 +140,58 @@ sigalarm_handler(int signo __unused) need_progress = 1; } -/* ARGSUSED */ +static void terminate(int signo) __dead2; +static void +terminate(int signo) +{ + kill_signal = signo; + summary(); + (void)fflush(stderr); + raise(kill_signal); + /* NOT REACHED */ + _exit(1); +} + +static sig_atomic_t in_io = 0; +static sig_atomic_t sigint_seen = 0; + +static void +sigint_handler(int signo __unused) +{ + atomic_signal_fence(memory_order_acquire); + if (in_io) + terminate(SIGINT); + sigint_seen = 1; +} + void -terminate(int sig) +prepare_io(void) { + struct sigaction sa; + int error; + + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_NODEFER | SA_RESETHAND; + sa.sa_handler = sigint_handler; + error = sigaction(SIGINT, &sa, 0); + if (error != 0) + err(1, "sigaction"); +} - summary(); - _exit(sig == 0 ? 0 : 1); +void +before_io(void) +{ + in_io = 1; + atomic_signal_fence(memory_order_seq_cst); + if (sigint_seen) + terminate(SIGINT); +} + +void +after_io(void) +{ + in_io = 0; + atomic_signal_fence(memory_order_seq_cst); + if (sigint_seen) + terminate(SIGINT); } |