based on commit 64b2b7c08d427796d75411f5d3ea46e585ad2d4b
Author: Chet Ramey <chet.ramey@case.edu>
Date:   Mon Mar 27 09:28:12 2023 -0400

    fixes for glibc time/gettimeofday issue; fix issue with history file containing one line too few if saving timestamps; fix for signal arriving while displaying readline completions

---
 histfile.c |   60 ++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 44 insertions(+), 16 deletions(-)

--- a/histfile.c
+++ b/histfile.c	2025-05-02 15:48:40.000000000 +0200
@@ -526,10 +548,14 @@ history_truncate_file (const char *fname
 
   buffer = (char *)NULL;
   filename = history_filename (fname);
+  if (filename == 0)
+    return 0;
   tempname = 0;
-  file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
+  file = open (filename, O_RDONLY|O_BINARY, 0666);
   rv = exists = 0;
 
+  orig_lines = lines;
+
   /* Don't try to truncate non-regular files. */
   if (file == -1 || fstat (file, &finfo) == -1)
     {
@@ -578,6 +604,15 @@ history_truncate_file (const char *fname
       goto truncate_exit;
     }
 
+  /* Don't bother with any of this if we're truncating to zero length. */
+  if (lines == 0)
+    {
+      close (file);
+      buffer[chars_read = 0] = '\0';
+      bp = buffer;
+      goto truncate_write;
+    }
+
   chars_read = read (file, buffer, file_size);
   close (file);
 
@@ -586,31 +621,38 @@ history_truncate_file (const char *fname
       rv = (chars_read < 0) ? errno : 0;
       goto truncate_exit;
     }
+  buffer[chars_read] = '\0';	/* for the initial check of bp1[1] */
 
-  orig_lines = lines;
   /* Count backwards from the end of buffer until we have passed
      LINES lines.  bp1 is set funny initially.  But since bp[1] can't
      be a comment character (since it's off the end) and *bp can't be
-     both a newline and the history comment character, it should be OK. */
-  for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
+     both a newline and the history comment character, it should be OK.
+     If we are writing history timestamps, we need to add one to LINES
+     because we decrement it one extra time the first time through the loop
+     and we need the final timestamp line. */
+  lines += history_write_timestamps;
+  for (bp1 = bp = buffer + chars_read - 1; lines > 0 && bp > buffer; bp--)
     {
       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
 	lines--;
       bp1 = bp;
     }
 
-  /* If this is the first line, then the file contains exactly the
+  /* This is the right line, so move to its start. If we're writing history
+     timestamps, we want to go back until *bp == '\n' and bp1 starts a
+     history timestamp. If we're not, just move back to *bp == '\n'.
+     If this is the first line, then the file contains exactly the
      number of lines we want to truncate to, so we don't need to do
-     anything.  It's the first line if we don't find a newline between
-     the current value of i and 0.  Otherwise, write from the start of
-     this line until the end of the buffer. */
+     anything, and we'll end up with bp == buffer.
+     Otherwise, write from the start of this line until the end of the
+     buffer. */
   for ( ; bp > buffer; bp--)
     {
-      if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
-        {
+      if (*bp == '\n' && (history_write_timestamps == 0 || HIST_TIMESTAMP_START(bp1)))
+	{
 	  bp++;
 	  break;
-        }
+	}
       bp1 = bp;
     }
 
@@ -624,17 +666,25 @@ history_truncate_file (const char *fname
       goto truncate_exit;
     }
 
+truncate_write:
   tempname = history_tempfile (filename);
 
+  rv = 0;
   if ((file = open (tempname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1)
     {
       if (write (file, bp, chars_read - (bp - buffer)) < 0)
-	rv = errno;
-
-      if (fstat (file, &nfinfo) < 0 && rv == 0)
-	rv = errno;
+	{
+	  rv = errno;
+	  close (file);
+	}
+
+      if (rv == 0 && fstat (file, &nfinfo) < 0)
+	{
+	  rv = errno;
+	  close (file);
+	}
 
-      if (close (file) < 0 && rv == 0)
+      if (rv == 0 && close (file) < 0)
 	rv = errno;
     }
   else
