[pacman-dev] [PATCH 1/3] repo-add: Avoid race condition in signal handlers

Lukas Fleischer archlinux at cryptocrack.de
Thu Oct 13 11:23:19 EDT 2011


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 at cryptocrack.de>
---
 scripts/repo-add.sh.in |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in
index 29b150c..d147b87 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"
-- 
1.7.7



More information about the pacman-dev mailing list