[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