zsh-workers
 help / color / mirror / code / Atom feed
From: Yutian Li <hotpxless@gmail.com>
To: zsh-workers@zsh.org
Subject: [PATCH] Fix an issue where SIGINT leaves readhistfile in inconsistent state
Date: Sat, 16 Feb 2019 23:40:15 -0500	[thread overview]
Message-ID: <CABvSBniueJdEVQ8D7EMKsoU2z2FD2M=ecUcuc4gEW4XbwYxajA@mail.gmail.com> (raw)

Dear all,

Thanks for perfecting this wonderful project. I've been using it for
years, and it's my first time trying to contribute back to the
community. So definitely let me know if my patch needs more work. :)

The issue I encountered is, when Zsh receives a SIGINT, it sets
errflag |= ERRFLAG_INT so it will break out of the loop in
readhistfile. But before we entered this loop we have already set
lasthist.fsiz = sb.st_size and lasthist.mtim = sb.st_mtime so it looks
like we have processed the history file up to the end already. And
next time readhistfile is called, it will skip all processing and
assume we have the entire history. This leaves Zsh in an inconsistent
state, where history from different sessions could be lost.

As a quick reproduction, setopt share_history, set HISTFILE
accordingly and open two sessions. In one session, do a bunch of
```
echo a
echo b
echo c
echo d
```
Then in the second session, do
```
<Ctrl-C>
history
```
In the history shown, you'll only see `echo a` but not the rest. The
reason is after Zsh processed the first line, and since Ctrl-C sets
`ERRFLAG_INT`, it will stop processing histories but think it has
processed everything up to the end of the file. So now that history is
basically eaten up. And worse still, if the history file gets
truncated/rewritten/`fc -W` at the end of the session, that history
will be lost forever.

My proposed fix is to just add another flag to tell us if we've been
interrupted from last time. If so, we don't skip processing.

Thanks,
Yutian

diff --git a/Src/hist.c b/Src/hist.c
index dbdc1e4e5..e3950e064 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -216,6 +216,7 @@ static struct histfile_stats {
     char *text;
     time_t stim, mtim;
     off_t fpos, fsiz;
+    int interrupted;
     zlong next_write_ev;
 } lasthist;

@@ -2544,11 +2545,13 @@ readhistfile(char *fn, int err, int readflags)
  sb.st_size == 0)
  return;
     if (readflags & HFILE_FAST) {
- if ((lasthist.fsiz == sb.st_size && lasthist.mtim == sb.st_mtime)
-     || lockhistfile(fn, 0))
+ if (!lasthist.interrupted &&
+     ((lasthist.fsiz == sb.st_size && lasthist.mtim == sb.st_mtime)
+     || lockhistfile(fn, 0)))
      return;
  lasthist.fsiz = sb.st_size;
  lasthist.mtim = sb.st_mtime;
+ lasthist.interrupted = 0;
     } else if ((ret = lockhistfile(fn, 1))) {
  if (ret == 2) {
      zwarn("locking failed for %s: %e: reading anyway", fn, errno);
@@ -2694,8 +2697,10 @@ readhistfile(char *fn, int err, int readflags)
       */
      if (uselex || remeta)
  freeheap();
-     if (errflag & ERRFLAG_INT)
+     if (errflag & ERRFLAG_INT) {
+ lasthist.interrupted=1;
  break;
+     }
  }
  if (start && readflags & HFILE_USE_OPTIONS) {
      zsfree(lasthist.text);

             reply	other threads:[~2019-02-17  4:41 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20190217044201epcas4p4ca093a5748a17d62dc9c5d418d0125c1@epcas4p4.samsung.com>
2019-02-17  4:40 ` Yutian Li [this message]
2019-02-18 10:11   ` Peter Stephenson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABvSBniueJdEVQ8D7EMKsoU2z2FD2M=ecUcuc4gEW4XbwYxajA@mail.gmail.com' \
    --to=hotpxless@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).