Other dd implementations always show the status on exit, whether success
or failure. Fix that by using xsigatexit() (and clarify the comment for
that function a little, since it didn't previously address the "at exit"
part of its behavior at all).

This also fixes SIGUSR1 behavior so that we show the status immediately
rather than on the next trip round the read/write loop.

Tested with `dd of=/dev/full`, sending SIGUSR1 twice from another shell
(to see the status immediately each time, without exiting), then hitting
^C (to see the status and then exiting), then restarting dd and hitting
enter (to see a write error followed by the status before exiting).

Bug: https://issuetracker.google.com/177017283
---
 lib/lib.c         |  7 ++++---
 toys/pending/dd.c | 18 +++++-------------
 2 files changed, 9 insertions(+), 16 deletions(-)
From 292d8361b94c96bd676a3574152f6d4ffcea29c1 Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Tue, 23 Feb 2021 14:24:19 -0800
Subject: [PATCH] dd: simplify signal handling and fix status output.

Other dd implementations always show the status on exit, whether success
or failure. Fix that by using xsigatexit() (and clarify the comment for
that function a little, since it didn't previously address the "at exit"
part of its behavior at all).

This also fixes SIGUSR1 behavior so that we show the status immediately
rather than on the next trip round the read/write loop.

Tested with `dd of=/dev/full`, sending SIGUSR1 twice from another shell
(to see the status immediately each time, without exiting), then hitting
^C (to see the status and then exiting), then restarting dd and hitting
enter (to see a write error followed by the status before exiting).

Bug: https://issuetracker.google.com/177017283
---
 lib/lib.c         |  7 ++++---
 toys/pending/dd.c | 18 +++++-------------
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/lib/lib.c b/lib/lib.c
index 06e39169..87bda4f6 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -911,9 +911,10 @@ void exit_signal(int sig)
   xexit();
 }
 
-// Install the same handler on every signal that defaults to killing the
-// process, calling the handler on the way out. Calling multiple times
-// adds the handlers to a list, to be called in order.
+// Install an atexit handler. Also install the same handler on every signal
+// that defaults to killing the process, calling the handler on the way out.
+// Calling multiple times adds the handlers to a list, to be called in LIFO
+// order.
 void sigatexit(void *handler)
 {
   struct arg_list *al = 0;
diff --git a/toys/pending/dd.c b/toys/pending/dd.c
index 8f4e711e..199e5914 100644
--- a/toys/pending/dd.c
+++ b/toys/pending/dd.c
@@ -98,8 +98,8 @@ static void status()
   }
 }
 
-static void dd_sigint(int sig) {
-  status();
+static void dd_sigint(int sig)
+{
   toys.exitval = sig|128;
   xexit();
 }
@@ -174,8 +174,9 @@ void dd_main()
   }
   if (bs) TT.in.sz = TT.out.sz = bs;
 
-  signal(SIGINT, dd_sigint);
-  signal(SIGUSR1, generic_signal);
+  sigatexit(status);
+  xsignal(SIGINT, dd_sigint);
+  xsignal(SIGUSR1, status);
   gettimeofday(&TT.start, NULL);
 
   // For bs=, in/out is done as it is. so only in.sz is enough.
@@ -238,13 +239,6 @@ void dd_main()
     int chunk = bytes_left < TT.in.sz ? bytes_left : TT.in.sz;
     ssize_t n;
 
-    // Show progress and exit on SIGINT or just continue on SIGUSR1.
-    if (toys.signal) {
-      status();
-      if (toys.signal==SIGINT) exit_signal(toys.signal);
-      toys.signal = 0;
-    }
-
     TT.in.bp = TT.in.buff + TT.in.count;
     if (TT.conv & _DD_conv_sync) memset(TT.in.bp, 0, TT.in.sz);
     if (!(n = read(TT.in.fd, TT.in.bp, chunk))) break;
@@ -288,6 +282,4 @@ void dd_main()
   close(TT.in.fd);
   close(TT.out.fd);
   if (TT.in.buff) free(TT.in.buff);
-
-  status();
 }
-- 
2.30.0.617.g56c4b15f3c-goog

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to