Server: correctly handle Accepters lifetime

When exiting kakoune, ClientAccepters (now Server::Accepter) could
stay alive, which left an FDWatcher in the EventManager triggering
an assert. Now Server is handling their lifetime.
This commit is contained in:
Maxime Coste 2014-03-25 09:21:20 +00:00
parent 2a23ce1987
commit 0bc57e43d2
2 changed files with 17 additions and 6 deletions

View File

@ -479,10 +479,10 @@ void send_command(const String& session, const String& command)
// * When a nul byte is recieved, the socket is handed to a new Client along // * When a nul byte is recieved, the socket is handed to a new Client along
// with the command. // with the command.
// * When the connection is closed, the command is run in an empty context. // * When the connection is closed, the command is run in an empty context.
class ClientAccepter class Server::Accepter
{ {
public: public:
ClientAccepter(int socket) Accepter(int socket)
: m_socket_watcher(socket, [this](FDWatcher&) { handle_available_input(); }) {} : m_socket_watcher(socket, [this](FDWatcher&) { handle_available_input(); }) {}
private: private:
@ -508,14 +508,14 @@ private:
} }
catch (client_removed&) {} catch (client_removed&) {}
close(socket); close(socket);
delete this; Server::instance().remove_accepter(this);
return; return;
} }
if (c == 0) // end of initial command stream, go to interactive ui mode if (c == 0) // end of initial command stream, go to interactive ui mode
{ {
ClientManager::instance().create_client( ClientManager::instance().create_client(
std::unique_ptr<UserInterface>{new RemoteUI{socket}}, m_buffer); std::unique_ptr<UserInterface>{new RemoteUI{socket}}, m_buffer);
delete this; Server::instance().remove_accepter(this);
return; return;
} }
else else
@ -547,7 +547,7 @@ Server::Server(String session_name)
if (listen(listen_sock, 4) == -1) if (listen(listen_sock, 4) == -1)
throw runtime_error("unable to listen on socket " + filename); throw runtime_error("unable to listen on socket " + filename);
auto accepter = [](FDWatcher& watcher) { auto accepter = [this](FDWatcher& watcher) {
sockaddr_un client_addr; sockaddr_un client_addr;
socklen_t client_addr_len = sizeof(sockaddr_un); socklen_t client_addr_len = sizeof(sockaddr_un);
int sock = accept(watcher.fd(), (sockaddr*) &client_addr, &client_addr_len); int sock = accept(watcher.fd(), (sockaddr*) &client_addr, &client_addr_len);
@ -555,7 +555,7 @@ Server::Server(String session_name)
throw runtime_error("accept failed"); throw runtime_error("accept failed");
fcntl(sock, F_SETFD, FD_CLOEXEC); fcntl(sock, F_SETFD, FD_CLOEXEC);
new ClientAccepter{sock}; m_accepters.emplace_back(new Accepter{sock});
}; };
m_listener.reset(new FDWatcher{listen_sock, accepter}); m_listener.reset(new FDWatcher{listen_sock, accepter});
} }
@ -572,4 +572,11 @@ Server::~Server()
close_session(); close_session();
} }
void Server::remove_accepter(Accepter* accepter)
{
auto it = find(m_accepters, accepter);
kak_assert(it != m_accepters.end());
m_accepters.erase(it);
}
} }

View File

@ -48,8 +48,12 @@ struct Server : public Singleton<Server>
void close_session(); void close_session();
private: private:
class Accepter;
void remove_accepter(Accepter* accepter);
String m_session; String m_session;
std::unique_ptr<FDWatcher> m_listener; std::unique_ptr<FDWatcher> m_listener;
std::vector<std::unique_ptr<Accepter>> m_accepters;
}; };
} }