Detect ungraceful exits, and backup modified buffers in these cases

This commit is contained in:
Maxime Coste 2015-10-08 13:43:39 +01:00
parent 3098cd12f8
commit 7776c38755
6 changed files with 19 additions and 11 deletions

View File

@ -86,9 +86,9 @@ void Client::handle_available_input(EventMode mode)
context().print_status({ error.what().str(), get_face("Error") }); context().print_status({ error.what().str(), get_face("Error") });
context().hooks().run_hook("RuntimeError", error.what(), context()); context().hooks().run_hook("RuntimeError", error.what(), context());
} }
catch (Kakoune::client_removed&) catch (Kakoune::client_removed& removed)
{ {
ClientManager::instance().remove_client(*this); ClientManager::instance().remove_client(*this, removed.graceful);
} }
} }

View File

@ -50,9 +50,9 @@ Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
client->context().hooks().run_hook("RuntimeError", error.what(), client->context().hooks().run_hook("RuntimeError", error.what(),
client->context()); client->context());
} }
catch (Kakoune::client_removed&) catch (Kakoune::client_removed& removed)
{ {
m_clients.pop_back(); remove_client(*client, removed.graceful);
return nullptr; return nullptr;
} }
@ -69,13 +69,16 @@ void ClientManager::handle_pending_inputs() const
client->handle_available_input(EventMode::Pending); client->handle_available_input(EventMode::Pending);
} }
void ClientManager::remove_client(Client& client) void ClientManager::remove_client(Client& client, bool graceful)
{ {
auto it = find_if(m_clients, auto it = find_if(m_clients,
[&](const std::unique_ptr<Client>& ptr) [&](const std::unique_ptr<Client>& ptr)
{ return ptr.get() == &client; }); { return ptr.get() == &client; });
kak_assert(it != m_clients.end()); kak_assert(it != m_clients.end());
m_clients.erase(it); m_clients.erase(it);
if (not graceful and m_clients.empty())
BufferManager::instance().backup_modified_buffers();
} }
WindowAndSelections ClientManager::get_free_window(Buffer& buffer) WindowAndSelections ClientManager::get_free_window(Buffer& buffer)

View File

@ -7,7 +7,12 @@
namespace Kakoune namespace Kakoune
{ {
struct client_removed{}; struct client_removed
{
client_removed(bool graceful) : graceful{graceful} {}
const bool graceful;
};
struct WindowAndSelections struct WindowAndSelections
{ {
@ -39,7 +44,7 @@ public:
Client* get_client_ifp(StringView name); Client* get_client_ifp(StringView name);
Client& get_client(StringView name); Client& get_client(StringView name);
bool validate_client_name(StringView name) const; bool validate_client_name(StringView name) const;
void remove_client(Client& client); void remove_client(Client& client, bool graceful);
using ClientList = Vector<std::unique_ptr<Client>, MemoryDomain::Client>; using ClientList = Vector<std::unique_ptr<Client>, MemoryDomain::Client>;
using iterator = ClientList::const_iterator; using iterator = ClientList::const_iterator;

View File

@ -299,7 +299,7 @@ void quit()
} }
} }
// unwind back to this client event handler. // unwind back to this client event handler.
throw client_removed{}; throw client_removed{ true };
} }
const CommandDesc quit_cmd = { const CommandDesc quit_cmd = {

View File

@ -309,7 +309,7 @@ void create_local_client(std::unique_ptr<UserInterface> ui, StringView init_comm
signal(SIGHUP, [](int) { signal(SIGHUP, [](int) {
if (client) if (client)
ClientManager::instance().remove_client(*client); ClientManager::instance().remove_client(*client, false);
client = nullptr; client = nullptr;
}); });
} }

View File

@ -391,12 +391,12 @@ Key RemoteUI::get_key()
} }
catch (peer_disconnected&) catch (peer_disconnected&)
{ {
throw client_removed{}; throw client_removed{ false };
} }
catch (socket_error&) catch (socket_error&)
{ {
write_to_debug_buffer("ungraceful deconnection detected"); write_to_debug_buffer("ungraceful deconnection detected");
throw client_removed{}; throw client_removed{ false };
} }
} }