Fix multi-client server suspend

This commit is contained in:
Maxime Coste 2019-09-09 20:11:04 +10:00
parent f43ac3d78b
commit 006083c6f8
3 changed files with 37 additions and 42 deletions

View File

@ -477,7 +477,6 @@ void register_options()
static Client* local_client = nullptr; static Client* local_client = nullptr;
static int local_client_exit = 0; static int local_client_exit = 0;
static UserInterface* local_ui = nullptr;
static bool convert_to_client_pending = false; static bool convert_to_client_pending = false;
enum class UIType enum class UIType
@ -550,26 +549,10 @@ std::unique_ptr<UserInterface> create_local_ui(UIType ui_type)
{ {
LocalUI() LocalUI()
{ {
kak_assert(not local_ui); set_signal_handler(SIGTSTP, [](int) {
local_ui = this;
m_old_sigtstp = set_signal_handler(SIGTSTP, [](int) {
if (ClientManager::instance().count() == 1 and if (ClientManager::instance().count() == 1 and
*ClientManager::instance().begin() == local_client) *ClientManager::instance().begin() == local_client)
{ NCursesUI::instance().suspend();
// Suspend normally if we are the only client
auto current = set_signal_handler(SIGTSTP, static_cast<LocalUI*>(local_ui)->m_old_sigtstp);
sigset_t unblock_sigtstp, old_mask;
sigemptyset(&unblock_sigtstp);
sigaddset(&unblock_sigtstp, SIGTSTP);
sigprocmask(SIG_UNBLOCK, &unblock_sigtstp, &old_mask);
raise(SIGTSTP);
set_signal_handler(SIGTSTP, current);
sigprocmask(SIG_SETMASK, &old_mask, nullptr);
}
else else
convert_to_client_pending = true; convert_to_client_pending = true;
}); });
@ -577,23 +560,17 @@ std::unique_ptr<UserInterface> create_local_ui(UIType ui_type)
~LocalUI() override ~LocalUI() override
{ {
set_signal_handler(SIGTSTP, m_old_sigtstp);
local_client = nullptr; local_client = nullptr;
local_ui = nullptr; if (convert_to_client_pending or
if (not convert_to_client_pending and ClientManager::instance().empty())
not ClientManager::instance().empty()) return;
{
if (fork_server_to_background()) if (fork_server_to_background())
{ {
this->NCursesUI::~NCursesUI(); this->NCursesUI::~NCursesUI();
exit(local_client_exit); exit(local_client_exit);
} }
} }
}
private:
using SigHandler = void (*)(int);
SigHandler m_old_sigtstp;
}; };
if (not isatty(1)) if (not isatty(1))

View File

@ -373,6 +373,7 @@ NCursesUI::NCursesUI()
set_signal_handler(SIGWINCH, &signal_handler<&resize_pending>); set_signal_handler(SIGWINCH, &signal_handler<&resize_pending>);
set_signal_handler(SIGHUP, &signal_handler<&sighup_raised>); set_signal_handler(SIGHUP, &signal_handler<&sighup_raised>);
set_signal_handler(SIGTSTP, [](int){ NCursesUI::instance().suspend(); });
check_resize(true); check_resize(true);
redraw(false); redraw(false);
@ -390,6 +391,29 @@ NCursesUI::~NCursesUI()
tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios); tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios);
set_signal_handler(SIGWINCH, SIG_DFL); set_signal_handler(SIGWINCH, SIG_DFL);
set_signal_handler(SIGCONT, SIG_DFL); set_signal_handler(SIGCONT, SIG_DFL);
set_signal_handler(SIGTSTP, SIG_DFL);
}
void NCursesUI::suspend()
{
bool mouse_enabled = m_mouse_enabled;
enable_mouse(false);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios);
auto current = set_signal_handler(SIGTSTP, SIG_DFL);
sigset_t unblock_sigtstp, old_mask;
sigemptyset(&unblock_sigtstp);
sigaddset(&unblock_sigtstp, SIGTSTP);
sigprocmask(SIG_UNBLOCK, &unblock_sigtstp, &old_mask);
raise(SIGTSTP); // suspend here
set_signal_handler(SIGTSTP, current);
sigprocmask(SIG_SETMASK, &old_mask, nullptr);
check_resize(true);
set_raw_mode();
enable_mouse(mouse_enabled);
} }
void NCursesUI::set_raw_mode() const void NCursesUI::set_raw_mode() const
@ -612,15 +636,7 @@ Optional<Key> NCursesUI::get_next_key()
return {Key::Backspace}; return {Key::Backspace};
if (c == control('z')) if (c == control('z'))
{ {
bool mouse_enabled = m_mouse_enabled;
enable_mouse(false);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios);
kill(0, SIGTSTP); // We suspend at this line kill(0, SIGTSTP); // We suspend at this line
check_resize(true);
set_raw_mode();
enable_mouse(mouse_enabled);
return {}; return {};
} }
if (c < 27) if (c < 27)

View File

@ -17,7 +17,7 @@ namespace Kakoune
struct NCursesWin; struct NCursesWin;
class NCursesUI : public UserInterface class NCursesUI : public UserInterface, public Singleton<NCursesUI>
{ {
public: public:
NCursesUI(); NCursesUI();
@ -57,6 +57,8 @@ public:
static void abort(); static void abort();
void suspend();
struct Rect struct Rect
{ {
DisplayCoord pos; DisplayCoord pos;
@ -117,7 +119,7 @@ private:
Window m_window; Window m_window;
DisplayCoord m_dimensions; DisplayCoord m_dimensions;
termios m_original_termios; termios m_original_termios{};
void set_raw_mode() const; void set_raw_mode() const;