diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc index d3567e021..4696bd51a 100644 --- a/src/libcmd/repl-interacter.cc +++ b/src/libcmd/repl-interacter.cc @@ -1,6 +1,8 @@ #include #include #include +#include +#include #ifdef READLINE #include @@ -176,15 +178,27 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT if (!s) return false; - write_history(historyFile.c_str()); + this->writeHistory(); input += s; input += '\n'; return true; } +void ReadlineLikeInteracter::writeHistory() +{ + if (write_history(historyFile.c_str()) != 0) { + // write_history returns the result of fclose() (which also flushes). + // We should explicitly ignore these errors, but log them so the user + // isn't confused why their history is getting eaten. + int const fcloseErr = errno; + std::string_view const errMsg(std::strerror(fcloseErr)); + warn("ignoring error writing repl history to %s: %s", this->historyFile, errMsg); + } +} + ReadlineLikeInteracter::~ReadlineLikeInteracter() { - write_history(historyFile.c_str()); + this->writeHistory(); } AutomationInteracter::Guard AutomationInteracter::init(detail::ReplCompleterMixin *) diff --git a/src/libcmd/repl-interacter.hh b/src/libcmd/repl-interacter.hh index c31b1a1e6..8f815fceb 100644 --- a/src/libcmd/repl-interacter.hh +++ b/src/libcmd/repl-interacter.hh @@ -42,6 +42,11 @@ public: } virtual Guard init(detail::ReplCompleterMixin * repl) override; virtual bool getLine(std::string & input, ReplPromptType promptType) override; + /** Writes the current history to the history file. + * + * This function logs but ignores errors from readline's write_history(). + */ + virtual void writeHistory(); virtual ~ReadlineLikeInteracter() override; };