Skip to content

Commit

Permalink
Add support for db locking in zsh (via flock)
Browse files Browse the repository at this point in the history
This commit ensures the database is locked before reading and updating
when used in zsh. We load the zsh/system module which provides the
zsystem flock command to perform advisory file locking.

A separate code path is needed when updating the database entry because
replacing the file (via mv) would cause any process waiting for a lock
to fail. Here we simply clobber the database with the contents of the
tempfile.
  • Loading branch information
mafredri committed Mar 21, 2019
1 parent bb23b74 commit 1eb243c
Showing 1 changed file with 27 additions and 4 deletions.
31 changes: 27 additions & 4 deletions z.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ _z() {

# maintain the data file
local tempfile="$(mktemp "${datafile}.XXXXXXXX")"
if [ "$_Z_USE_ZSYSTEM_FLOCK" -eq 1 ]; then
# make sure datafile exists (for locking)
[ -f "$datafile" ] || touch "$datafile"
local lockfd
# grab exclusive lock (released when function exits)
zsystem flock -f lockfd "$datafile" || return
fi
_z_dirs | awk -v path="$*" -v now="$(date +%s)" -F"|" '
BEGIN {
rank[path] = 1
Expand All @@ -85,12 +92,20 @@ _z() {
} else for( x in rank ) print x "|" rank[x] "|" time[x]
}
' 2>/dev/null >| "$tempfile"
# do our best to avoid clobbering the datafile in a race condition.
if [ $? -ne 0 -a -f "$datafile" ]; then
local ret=$?
if [ "$_Z_USE_ZSYSTEM_FLOCK" -eq 1 ]; then
# replace contents of datafile with tempfile
env cat "$tempfile" >| "$datafile"
[ "$_Z_OWNER" ] && chown $_Z_OWNER:"$(id -ng $_Z_OWNER)" "$datafile"
env rm -f "$tempfile"
else
[ "$_Z_OWNER" ] && chown $_Z_OWNER:"$(id -ng $_Z_OWNER)" "$tempfile"
env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile"
# do our best to avoid clobbering the datafile in a race condition.
if [ $ret -ne 0 -a -f "$datafile" ]; then
env rm -f "$tempfile"
else
[ "$_Z_OWNER" ] && chown $_Z_OWNER:"$(id -ng $_Z_OWNER)" "$tempfile"
env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile"
fi
fi

# tab completion
Expand Down Expand Up @@ -216,6 +231,14 @@ alias ${_Z_CMD:-z}='_z 2>&1'

[ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P"

if type zmodload >/dev/null 2>&1; then
# load zsh/system for the zsystem flock builtin
zmodload zsh/system &>/dev/null
if zsystem supports flock &>/dev/null; then
_Z_USE_ZSYSTEM_FLOCK=1
fi
fi

if type compctl >/dev/null 2>&1; then
# zsh
[ "$_Z_NO_PROMPT_COMMAND" ] || {
Expand Down

0 comments on commit 1eb243c

Please sign in to comment.