summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Fleischer <archlinux@cryptocrack.de>2011-10-13 17:23:19 +0200
committerDan McGee <dan@archlinux.org>2011-10-13 11:20:03 -0500
commitd4c97ea2f64cafd3e14e2817d2b805f0b0d541f1 (patch)
tree4639bea0a033e8351fb575053a25060740efbd05
parent12642a299b9f4218f43ce8a4f1d9924cfae744ee (diff)
downloadpacman-d4c97ea2f64cafd3e14e2817d2b805f0b0d541f1.tar.xz
repo-add: Avoid race condition in signal handlers
There is a small chance that a user sends SIGINT (or any other signal that is trapped) when we're already in clean_up() which used to lead to trap_exit() being executed and the remaining code in clean_up() being skipped due to the bash signal/trap handler blocking EXIT (since its handler is already being executed, even if it's interrupted). In practice, this behaviour caused unexpected results (primarily because pressing ^C at the wrong time left a lock file behind): $ ./repo-add extra.db.tar.gz foobar ==> Extracting database to a temporary location... ^C ==> ERROR: Aborted by user! Exiting... $ ./repo-add extra.db.tar.gz foobar ==> Extracting database to a temporary location... ==> ERROR: File 'foobar' not found. ==> No packages modified, nothing to do. ^C ==> ERROR: Aborted by user! Exiting... $ ./repo-add extra.db.tar.gz foobar ==> ERROR: Failed to acquire lockfile: extra.db.tar.gz.lck. ==> ERROR: Held by process 18522 Fix this and reduce the chance of race conditions in signal handlers by: * Unhooking all traps in both clean_up() and trap_exit(). * Call clean_up() explicitly in trap_exit() to make sure we remove the lock file and the temporary directory even if we send SIGINT when clean_up() is already being executed but didn't reach the unhook code yet. Also, add an optional parameter to clean_up() to allow for setting an explicit exit code when we call clean_up() from trap_exit(). Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--scripts/repo-add.sh.in10
1 files changed, 8 insertions, 2 deletions
diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in
index 29b150c8..d147b875 100644
--- a/scripts/repo-add.sh.in
+++ b/scripts/repo-add.sh.in
@@ -520,13 +520,19 @@ remove() {
}
trap_exit() {
+ # unhook all traps to avoid race conditions
+ trap '' EXIT TERM HUP QUIT INT ERR
+
echo
error "$@"
- exit 1
+ clean_up 1
}
clean_up() {
- local exit_code=$?
+ local exit_code=${1:-$?}
+
+ # unhook all traps to avoid race conditions
+ trap '' EXIT TERM HUP QUIT INT ERR
[[ -d $tmpdir ]] && rm -rf "$tmpdir"
(( CLEAN_LOCK )) && [[ -f $LOCKFILE ]] && rm -f "$LOCKFILE"