aboutsummaryrefslogtreecommitdiff
path: root/bin/dd/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/dd/misc.c')
-rw-r--r--bin/dd/misc.c64
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);
}