From patchwork Sat Jan 10 18:46:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 4608 Received: (qmail 20041 invoked by alias); 10 Jan 2015 18:46:24 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 20029 invoked by uid 89); 10 Jan 2015 18:46:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-qg0-f51.google.com Received: from mail-qg0-f51.google.com (HELO mail-qg0-f51.google.com) (209.85.192.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 10 Jan 2015 18:46:21 +0000 Received: by mail-qg0-f51.google.com with SMTP id i50so13197457qgf.10 for ; Sat, 10 Jan 2015 10:46:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YDB/11MUZObs9PXkOT8a9+8m+ikag5EmiA6WZN73nfE=; b=HHYMRzzluGNz3QV2KofmjrX47+RpRhv7edhEAhsLAA/WSIrOm4ehxlgZQdg6d4jpB4 xBUHUz8wXoIE3lG5Kbwh6oMXahWkAo0YQtbzO2nAjH4vUXANopoASemMEZIgtqZUFtBy SaukjXY6pqGwd0i9zYH9Pb0QfC4rMy/qPrqc9dzLPJKjofMQRTu+eqGl+VQ+CQ+R/ypB u/emrk9p3PN6abaZsm0N7g3s0pt6EV8kUbYU2ETpVd8neo+qtaKSZ+ETPcmj880G3B44 M3tt4MBe9254aeqQSJVZC7sndRFd1CUslg+VKM1D0q05+MGXwwJQlLf1F4ZfMKid3dLh 5JMg== X-Gm-Message-State: ALoCoQkRzHL/Xk5+6jWgquYFl9muvrFud0MHUGgybld+3FDBCpN1KurVLfWX0trbObiAxhEMjhE2 X-Received: by 10.140.81.166 with SMTP id f35mr35470047qgd.0.1420915579103; Sat, 10 Jan 2015 10:46:19 -0800 (PST) Received: from localhost.localdomain (ool-4353ac94.dyn.optonline.net. [67.83.172.148]) by mx.google.com with ESMTPSA id t67sm10298813qgt.11.2015.01.10.10.46.17 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 10 Jan 2015 10:46:18 -0800 (PST) From: Patrick Palka To: gdb-patches@sourceware.org Cc: Patrick Palka Subject: [PATCH] Append to input history file instead of overwriting it Date: Sat, 10 Jan 2015 13:46:10 -0500 Message-Id: <1420915570-5605-1-git-send-email-patrick@parcs.ath.cx> In-Reply-To: References: v2: Emit a warning if the first call to rename() fails with errno != ENOENT. Don't emit a warning if the second call to rename() fails with EEXIST. 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. --- gdb/event-top.c | 2 +- gdb/top.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- gdb/top.h | 2 ++ 3 files changed, 65 insertions(+), 4 deletions(-) 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..3d50aba 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -895,7 +895,66 @@ 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; + + local_history_filename = xstrprintf ("%s.%d", history_filename, getpid ()); + + ret = rename (history_filename, local_history_filename); + saved_errno = errno; + if (ret < 0 && saved_errno == ENOENT) + { + /* 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! */ + write_history (local_history_filename); + } + else if (ret < 0) + { + warning (_("Could not rename %s to %s: %s"), + history_filename, local_history_filename, strerror (saved_errno)); + goto out; + } + 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, strerror (saved_errno)); + +out: + xfree (local_history_filename); +} + /* Read one line from the command input stream `instream' into the local static buffer `linebuffer' (whose current length is `linelength'). @@ -1094,7 +1153,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 +1504,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);