-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Database is often lost #198
Comments
Just for reference and history, related old issue: #191 |
I did a quick hack for zsh to use advisory file locking, should prevent any database corruption. Furthermore, using @balta2ar feel free to try it out if you're interested: EDIT: Not sure this works as intended, will look closer tomorrow. diff --git a/z.sh b/z.shdiff --git a/z.sh b/z.sh
index 24e1272..e7cadbb 100644
--- a/z.sh
+++ b/z.sh
@@ -23,6 +23,8 @@
# * z -l foo # list matches instead of cd
# * z -c foo # restrict matches to subdirs of $PWD
+zmodload zsh/system
+
[ -d "${_Z_DATA:-$HOME/.z}" ] && {
echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
}
@@ -56,7 +58,9 @@ _z() {
done
# maintain the data file
- local tempfile="$datafile.$RANDOM"
+ local tempfile="$(mktemp "${datafile}.XXXXXXXX")"
+ local lockfd
+ zsystem flock -t 2 -f lockfd "$datafile" || return
awk < <(_z_dirs 2>/dev/null) -v path="$*" -v now="$(date +%s)" -F"|" '
BEGIN {
rank[path] = 1
@@ -80,13 +84,9 @@ _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
- 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
+ [ "$_Z_OWNER" ] && chown $_Z_OWNER:$(id -ng $_Z_OWNER) "$tempfile"
+ env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile"
+ zsystem flock -u $lockfd
# tab completion
elif [ "$1" = "--complete" -a -s "$datafile" ]; then |
Sure, I'm waiting for your signal. |
@balta2ar here's an updated patch. My uncertainty from before was with regards to using flock and then replacing the file with another (via diff --git a/z.sh b/z.shdiff --git a/z.sh b/z.sh
index 24e1272..da4f411 100644
--- a/z.sh
+++ b/z.sh
@@ -23,6 +23,8 @@
# * z -l foo # list matches instead of cd
# * z -c foo # restrict matches to subdirs of $PWD
+zmodload zsh/system
+
[ -d "${_Z_DATA:-$HOME/.z}" ] && {
echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
}
@@ -55,8 +57,14 @@ _z() {
case "$*" in "$exclude*") return;; esac
done
+ # make sure datafile exists (for locking)
+ [[ -f "$datafile" ]] || touch "$datafile"
+
# maintain the data file
- local tempfile="$datafile.$RANDOM"
+ local tempfile="$(mktemp "${datafile}.XXXXXXXX")"
+ local lockfd
+ # lock datafile, released when function exits
+ zsystem flock -f lockfd "$datafile" || return
awk < <(_z_dirs 2>/dev/null) -v path="$*" -v now="$(date +%s)" -F"|" '
BEGIN {
rank[path] = 1
@@ -80,13 +88,10 @@ _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
- 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
+ # replace contents of datafile with tempfile
+ env cat "$tempfile" >| "$datafile"
+ [ "$_Z_OWNER" ] && chown $_Z_OWNER:$(id -ng $_Z_OWNER) "$datafile"
+ env rm -f "$tempfile"
# tab completion
elif [ "$1" = "--complete" -a -s "$datafile" ]; then
|
@mafredri Thank you very much! I've applied the patch and did a short experiment trying to overwrite the DB. So far it seems to be acting good. But I'll keep an eye on it for while to be more sure. I wonder, do you think flock command could be used here so that it's not zsh-specific and could be used in bash as well? |
@balta2ar that command does not exist on macOS, for example, so it wouldn't really be cross-platform :(. |
It kind of beats the purpose of keeping |
Sorry, I'm not following... Why?
Yeah, you're right. But on the second hand, feature detection could be performed and it would still work without flock. It would work more reliably with it, though. Anyway, I'm just thinking of a way to have it merged. Now, if I get it right, this won't work in bash as there is no |
As in, we would only use
Would be a possibility, only beneficial for
Yes, correct, would not work in |
Thanks for clarifications! What I meant is that at the moment this patch renders Anyway, looks like there is a working solution and I'm ok with patching |
Ping? This makes z unusable for me. |
@dfaure-kdab it doesn't seem like rupa is active at the moment, but feel free to use #199 if you're using zsh. |
i'm aware of and thinking about this. I'm definitely not in any hurry to add dependencies, although I'm considering bringin back mktemp if that would help. It's tough for me to evaluate zsh stuff because: it's so configurable, so many people use it with an opinionated framework, and I don't use it. Anyone that can post a nice setup that reliably clobbers the db, that would be cool |
@rupa I can take a stab at creating a repro for you. PS. My PR does introduce the mktemp dependency, but no other. Uses feature detection to use flock if available (available in default configurations on systems that support flock). I can't think of many other methods that aren't racey in one form or another. |
The culprit of this is the switch to using a background process inside a subshell, coupled with the fact that I've layed down the basics here: ohmyzsh/ohmyzsh#7094 (comment), but the basic gist is that in zsh, You can reproduce this issue from a directory other than $HOME, with the following (save your .z file before attempting):
It should give many "no such file or directory" errors, while this one:
shouldn't. Notice that I'm referencing The downside of that is that That said, using a precmd hook means that each time the prompt is drawn _z will be called, with the associated cost in computation and IO that aren't doing anything useful. So here's my proposed fix: use the chpwd hook instead of the precmd one, which only runs after changing to another directory. This is the easiest, most direct fix, and it also makes sense. It will also have the effect that holding down the enter key will not spam _z with added work. Finally, there's an edge case even running it in a chwpd hook, which is cd-ing into two directories at once:
This will again use the same TL;DR Proposed change:
I hope that wasn't too verbose. Cheers! |
Ok, so now that #215 is closed because using chpwd is not suitable, the proposed fix is just referencing
Let me know if you want me to submit a PR. |
@mcornella Please do, I'd like to give it a try. |
I've submitted #247 |
Rupa: This would be worth looking into and dealing with, as use of zsh is going to go way up as Mac people move to Catalina, which is zsh by default (and actively deprecates bash). |
I experience that z will clear all visited paths from time to time. I don't know how to reproduce this, have happened three times the last three months. Using z on Git Bash on Windows 10. |
I've been suffering from this for a while now, and today decided that I should report. Basically, the issue is described here:
And the following comment:
@rupa Could you please look into this?
The text was updated successfully, but these errors were encountered: