From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id 0f325d12 for ; Sat, 9 Mar 2019 00:56:04 +0000 (UTC) Received: (qmail 25838 invoked by alias); 9 Mar 2019 00:55:25 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 44107 Received: (qmail 23292 invoked by uid 1010); 9 Mar 2019 00:55:25 -0000 X-Qmail-Scanner-Diagnostics: from granite.fifsource.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.100.2/25376. spamassassin: 3.4.2. Clear:RC:0(173.255.216.206):SA:0(-1.9/5.0):. Processed in 0.46694 secs); 09 Mar 2019 00:55:25 -0000 X-Envelope-From: phil+github-commits@fifi.org X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at fifi.org designates 173.255.216.206 as permitted sender) From: Philippe Troin To: Zsh hackers list Cc: Philippe Troin Subject: [PATCH 3/3] Delay closing the history file until the fcntl-lock is released. Date: Fri, 8 Mar 2019 16:54:42 -0800 Message-Id: <20190309005442.944477-3-phil+github-commits@fifi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190309005442.944477-1-phil+github-commits@fifi.org> References: <70520d027e2f5ddc09b2c78d543664b52341f450.camel@fifi.org> <20190309005442.944477-1-phil+github-commits@fifi.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Qmail-Scanner-2.11: added fake Content-Type header Content-Type: text/plain Closes are not delayed if zsh is not compiled with fcntl() lock or if the histfcntllock option isn't set. --- Src/hist.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/Src/hist.c b/Src/hist.c index 981316674..2d0b3eb0f 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -2527,6 +2527,63 @@ readhistline(int start, char **bufp, int *bufsiz, FILE *in) #ifdef HAVE_FCNTL_H static int flock_fd = -1; +#define FLOCK_MAX_FILES_TO_CLOSE 10 +static int flock_fds_to_close[FLOCK_MAX_FILES_TO_CLOSE] = { -1 }; +static FILE* flock_files_to_close[FLOCK_MAX_FILES_TO_CLOSE]; + +static int +closehistfd(int fd) { + int i; + + if (flock_fd < 0) { + return close(fd); + } + + for (i=0; i < FLOCK_MAX_FILES_TO_CLOSE; ++i) { + if (flock_fds_to_close[i] < 0) { + break; + } + } + + if (i >= FLOCK_MAX_FILES_TO_CLOSE) { + zerr("Ran out of flock_fds_to_close, increase the " + "FLOCK_MAX_FILES_TO_CLOSE limit (currently at %d) in hist.c.", + FLOCK_MAX_FILES_TO_CLOSE); + /* Close if we can't postpone */ + return close(fd); + } + + flock_fds_to_close[i] = fd; + + return 0; +} + +static int +closehistfile(FILE* fp) { + int i; + + if (flock_fd < 0) { + return fclose(fp); + } + + for (i=0; i < FLOCK_MAX_FILES_TO_CLOSE; ++i) { + if (! flock_files_to_close[i]) { + break; + } + } + + if (i >= FLOCK_MAX_FILES_TO_CLOSE) { + zerr("Ran out of flock_files_to_close, increase the " + "FLOCK_MAX_FILES_TO_CLOSE limit (currently at %d) in hist.c.", + FLOCK_MAX_FILES_TO_CLOSE); + /* Close if we can't postpone */ + return fclose(fp); + } + + flock_files_to_close[i] = fp; + + return 0; +} /* * Lock file using fcntl(). Return 0 on success, 1 on failure of @@ -2539,10 +2596,18 @@ flockhistfile(char *fn, int keep_trying) struct flock lck; long sleep_us = 0x10000; /* about 67 ms */ time_t end_time; + int i; if (flock_fd >= 0) return 0; /* already locked */ + /* Clear out the list of fds/file descriptors which will be closed + upon relinquising the lock */ + memset(flock_files_to_close, 0, sizeof(flock_files_to_close[0])*FLOCK_MAX_FILES_TO_CLOSE); + for (i=0; i < FLOCK_MAX_FILES_TO_CLOSE; ++i) { + flock_fds_to_close[i] = -1; + } + if ((flock_fd = open(unmeta(fn), O_RDWR | O_NOCTTY)) < 0) return errno == ENOENT ? 0 : 2; /* "successfully" locked missing file */ @@ -2575,12 +2640,36 @@ flockhistfile(char *fn, int keep_trying) static void funlockhistfile() { + int i; + if (flock_fd >= 0) { close(flock_fd); flock_fd = -1; } + + for (i=0; i < FLOCK_MAX_FILES_TO_CLOSE; ++i) { + if (flock_files_to_close[i]) { + fclose(flock_files_to_close[i]); + flock_files_to_close[i] = NULL; + } else { + break; + } + } + + for (i=0; i < FLOCK_MAX_FILES_TO_CLOSE; ++i) { + if (flock_fds_to_close[i] >= 0) { + close(flock_fds_to_close[i]); + flock_fds_to_close[i] = -1; + } else { + break; + } + } } -#endif + +#else /* ! HAVE_FCNTL_H */ +# define closehistfd(x) close(x) +# define closehistfile(x) fclose(x) +#endif /* ! HAVE_FCNTL_H */ /**/ void @@ -2768,7 +2857,7 @@ readhistfile(char *fn, int err, int readflags) zfree(buf, bufsiz); popheap(); - fclose(in); + closehistfile(in); } else if (err) zerr("can't read history file %s", fn); @@ -2860,7 +2949,7 @@ savehistfile(char *fn, int err, int writeflags) if (fd >=0) { out = fdopen(fd, "w"); if (!out) - close(fd); + closehistfd(fd); } else out = NULL; } @@ -2948,7 +3037,7 @@ savehistfile(char *fn, int err, int writeflags) lasthist.text = ztrdup(start); } } - if (fclose(out) < 0 && ret >= 0) + if (closehistfile(out) < 0 && ret >= 0) ret = -1; if (ret >= 0) { if (tmpfile) { -- 2.20.1