This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Append to input history file instead of overwriting it


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=08b13bdd82996fbd321111191d33233073584b98

commit 08b13bdd82996fbd321111191d33233073584b98
Author: Patrick Palka <patrick@parcs.ath.cx>
Date:   Mon Jan 12 17:51:33 2015 -0500

    Append to input history file instead of overwriting it
    
    This patch makes readline append new history lines to the GDB history
    file on exit instead of overwriting the entire history file on exit.
    This change allows us to run multiple simultaneous GDB sessions without
    having each session overwrite the added history of each other session on
    exit.
    
    Care must be taken to ensure that the history file doesn't get corrupted
    when multiple GDB processes are trying to simultaneously append to and
    then truncate it.  Safety is achieved in such a situation by using an
    intermediate local history file to mutually exclude multiple processes
    from simultaneously performing write operations on the global history
    file.
    
    gdb/ChangeLog:
    
    	* top.h (gdb_add_history): Declare.
    	* top.c (command_count): New variable.
    	(gdb_add_history): New function.
    	(gdb_safe_append_history): New static function.
    	(quit_force): Call it.
    	(command_line_input): Use gdb_add_history instead of
    	add_history.
    	* event-top.c (command_line_handler): Likewise.

Diff:
---
 gdb/ChangeLog   | 11 +++++++++
 gdb/event-top.c |  2 +-
 gdb/top.c       | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 gdb/top.h       |  2 ++
 4 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b661c54..acbea15 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2015-01-12  Patrick Palka  <patrick@parcs.ath.cx>
+
+	* top.h (gdb_add_history): Declare.
+	* top.c (command_count): New variable.
+	(gdb_add_history): New function.
+	(gdb_safe_append_history): New static function.
+	(quit_force): Call it.
+	(command_line_input): Use gdb_add_history instead of
+	add_history.
+	* event-top.c (command_line_handler): Likewise.
+
 2015-01-12  James Clarke  <jrtc27@jrtc27.com>  (tiny patch)
 
 	PR gdb/17046
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 13ddee2..bbda5dc 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -667,7 +667,7 @@ command_line_handler (char *rl)
 
   /* Add line to history if appropriate.  */
   if (*linebuffer && input_from_terminal_p ())
-    add_history (linebuffer);
+    gdb_add_history (linebuffer);
 
   /* Note: lines consisting solely of comments are added to the command
      history.  This is useful when you type a command, and then
diff --git a/gdb/top.c b/gdb/top.c
index b85ea1a..a1462a0 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -895,7 +895,74 @@ gdb_rl_operate_and_get_next (int count, int key)
 
   return rl_newline (1, key);
 }
-
+
+/* Number of user commands executed during this session.  */
+
+static int command_count = 0;
+
+/* Add the user command COMMAND to the input history list.  */
+
+void
+gdb_add_history (const char *command)
+{
+  add_history (command);
+  command_count++;
+}
+
+/* Safely append new history entries to the history file in a corruption-free
+   way using an intermediate local history file.  */
+
+static void
+gdb_safe_append_history (void)
+{
+  int ret, saved_errno;
+  char *local_history_filename;
+  struct cleanup *old_chain;
+
+  local_history_filename
+    = xstrprintf ("%s-gdb%d~", history_filename, getpid ());
+  old_chain = make_cleanup (xfree, local_history_filename);
+
+  ret = rename (history_filename, local_history_filename);
+  saved_errno = errno;
+  if (ret < 0 && saved_errno != ENOENT)
+    {
+      warning (_("Could not rename %s to %s: %s"),
+	       history_filename, local_history_filename,
+	       safe_strerror (saved_errno));
+    }
+  else
+    {
+      if (ret < 0)
+	{
+	  /* If the rename failed with ENOENT then either the global history
+	     file never existed in the first place or another GDB process is
+	     currently appending to it (and has thus temporarily renamed it).
+	     Since we can't distinguish between these two cases, we have to
+	     conservatively assume the first case and therefore must write out
+	     (not append) our known history to our local history file and try
+	     to move it back anyway.  Otherwise a global history file would
+	     never get created!  */
+	   gdb_assert (saved_errno == ENOENT);
+	   write_history (local_history_filename);
+	}
+      else
+	{
+	  append_history (command_count, local_history_filename);
+	  history_truncate_file (local_history_filename, history_max_entries);
+	}
+
+      ret = rename (local_history_filename, history_filename);
+      saved_errno = errno;
+      if (ret < 0 && saved_errno != EEXIST)
+        warning (_("Could not rename %s to %s: %s"),
+		 local_history_filename, history_filename,
+		 safe_strerror (saved_errno));
+    }
+
+  do_cleanups (old_chain);
+}
+
 /* Read one line from the command input stream `instream'
    into the local static buffer `linebuffer' (whose current length
    is `linelength').
@@ -1094,7 +1161,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
 
   /* Add line to history if appropriate.  */
   if (*linebuffer && input_from_terminal_p ())
-    add_history (linebuffer);
+    gdb_add_history (linebuffer);
 
   /* Save into global buffer if appropriate.  */
   if (repeat)
@@ -1445,7 +1512,7 @@ quit_force (char *args, int from_tty)
     {
       if (write_history_p && history_filename
 	  && input_from_terminal_p ())
-	write_history (history_filename);
+	gdb_safe_append_history ();
     }
   DO_PRINT_EX;
 
diff --git a/gdb/top.h b/gdb/top.h
index b68e896..987279b 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -79,6 +79,8 @@ extern int history_expansion_p;
 extern int server_command;
 extern char *lim_at_start;
 
+extern void gdb_add_history (const char *);
+
 extern void show_commands (char *args, int from_tty);
 
 extern void set_history (char *, int);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]