[Pkg-privacy-commits] [libgsecuredelete] 119/168: Fix termination by signal in the `sfill` wrapper

Ulrike Uhlig u-guest at moszumanska.debian.org
Thu Jul 7 20:06:46 UTC 2016


This is an automated email from the git hooks/post-receive script.

u-guest pushed a commit to branch master
in repository libgsecuredelete.

commit df59d6a0fedc8316e67283790c7da4db2aeb6127
Author: Colomban Wendling <ban at herbesfolles.org>
Date:   Thu May 24 18:53:39 2012 +0200

    Fix termination by signal in the `sfill` wrapper
    
    Trap (signal) handlers seems not to run when a child process is
    currently running.  Since when a trap handler is registered the
    corresponding signal is no more forwarded to the child processes,
    this means our handler may run a long time after the script actually
    received the signal.
    
    This was not acceptable in our case since we run commands that can take
    a very long time to complete, and if we receive a signal it's likely
    the user wanted to abort the operation, and we should then react
    quickly.
    
    Fortunately shells (at least `bash` and `dash`) trigger trap handlers
    when waiting for a background job to finish (using `wait`), so we run
    the time-consuming children in background and immediately wait for them
    to terminate, emulating synchronous run while giving our trap handler
    a chance to run immediately.
    
    Finally, we need to kill our background child process in the trap
    handler if any, since the signal won't be forwarded to them
    automatically.  Using `kill %1` in the handler should have been enough
    if `dash` supported it, but strangely enough this doesn't seem work in
    a trap handler (while it does with `bash`).  Moreover, `dash` doesn't
    export the background jobs to the sub-shells, disallowing workarounds
    like `jobs -p | xargs kill` or `kill $(jobs -p)` -- which both work
    under `bash`.
    So here the implementation is a bit ugly at emulating the thing, but it
    works quite well, and supports both `dash` and `bash`.
---
 gsd-sfill-helper.in | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/gsd-sfill-helper.in b/gsd-sfill-helper.in
index 78f8cc1..8c4809a 100644
--- a/gsd-sfill-helper.in
+++ b/gsd-sfill-helper.in
@@ -73,7 +73,36 @@ shift $(expr $OPTIND - 1)
 # do our work in a temp directory so in the worst case if we fail to cleanup we
 # don't leave the user with tons of temp files but a single directory
 dir=$(mktemp -d --tmpdir="$1") || die "failed to create temp directory"
-trap "rm -rf '$dir'" INT QUIT TERM EXIT
+
+# runs a command asynchronously and wait for the trap handler to run
+# immediately.  the pid of the launched command is in $cmdpid
+#
+# this allows for trap handlers to run while the command is running rather than
+# to wait until command termination before running.  since we expect the user
+# to maybe kill us to abort, we better react immediately rather than waiting
+# for a command that can take several minutes to complete -- and that the user
+# wants to stop.
+cmdpid=
+launch_cmd() {
+  "$@" &
+  cmdpid=$!
+  wait $cmdpid
+  cmdpid=
+}
+
+cleanup() {
+  echo 'Terminated by signal. Clean exit.' >&2
+  rm -rf '$dir'
+  
+  # kill current background job if any
+  # using kill %1 would be better but it doesn't seem to work with dash
+  [ -n "$cmdpid" ] && kill $cmdpid
+  
+  exit 1
+}
+
+trap "rm -rf '$dir'" EXIT
+trap cleanup INT QUIT TERM
 
 
 # wipe inodes, no workaround needed
@@ -82,7 +111,7 @@ if [ -n "$OPT_i" ] || [ -z "$OPT_I" ]; then
   inode_v=$OPT_v
   [ -z $OPT_i ] && inode_v=
   
-  "$SFILL" $OPT_f -i $OPT_l $inode_v $OPT_z "$dir"
+  launch_cmd "$SFILL" $OPT_f -i $OPT_l $inode_v $OPT_z "$dir"
 fi
 
 # wipe disk space, work around for file size limit
@@ -93,7 +122,7 @@ if [ -z "$OPT_i" ]; then
   while [ 1 ]; do
     file=$(mktemp --tmpdir="$dir") || die "failed to create temp file"
     
-    dd if="$input" of="$file" bs=8M conv=fdatasync 2>&1
+    launch_cmd dd if="$input" of="$file" bs=8M conv=fdatasync 2>&1
     
     # if the file we tried to create has size 0, guess there's actually no
     # space left on device
@@ -103,6 +132,7 @@ if [ -z "$OPT_i" ]; then
   sync
   progress_step
   
-  "$SRM" -r $OPT_f $OPT_l $OPT_z "$dir"
+  launch_cmd "$SRM" -r $OPT_f $OPT_l $OPT_z "$dir"
+  
   progress_step
 fi

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/libgsecuredelete.git



More information about the Pkg-privacy-commits mailing list