LibLine: Unregister signal handlers on destruction

This fixes an issue that shows up as a nice crash when "^R<enter>^C",
which is actually the event loop trying to call into a deleted object
(the search editor).
This commit is contained in:
AnotherTest 2021-01-09 03:40:07 +03:30 committed by Andreas Kling
parent d07ac4130f
commit 9b126a2250
Notes: sideshowbarker 2024-07-18 23:58:35 +09:00
3 changed files with 27 additions and 10 deletions

View file

@ -180,7 +180,7 @@ void Editor::set_default_keybinds()
Editor::Editor(Configuration configuration)
: m_configuration(move(configuration))
{
m_always_refresh = configuration.refresh_behaviour == Configuration::RefreshBehaviour::Eager;
m_always_refresh = m_configuration.refresh_behaviour == Configuration::RefreshBehaviour::Eager;
m_pending_chars = ByteBuffer::create_uninitialized(0);
get_terminal_size();
m_suggestion_display = make<XtermSuggestionDisplay>(m_num_lines, m_num_columns);
@ -451,19 +451,24 @@ void Editor::initialize()
for (auto& keybind : m_configuration.keybindings)
register_key_input_callback(keybind);
Core::EventLoop::register_signal(SIGINT, [this](int) {
interrupted();
});
if (m_configuration.m_signal_mode == Configuration::WithSignalHandlers) {
m_signal_handlers.append(Core::EventLoop::register_signal(SIGINT, [this](int) {
interrupted();
}));
Core::EventLoop::register_signal(SIGWINCH, [this](int) {
resized();
});
m_signal_handlers.append(Core::EventLoop::register_signal(SIGWINCH, [this](int) {
resized();
}));
}
m_initialized = true;
}
void Editor::interrupted()
{
if (m_is_searching)
return m_search_editor->interrupted();
if (!m_is_editing)
return;
@ -482,7 +487,7 @@ void Editor::interrupted()
m_buffer.clear();
m_is_editing = false;
restore();
m_notifier->set_event_mask(Core::Notifier::None);
m_notifier->set_enabled(false);
deferred_invoke([this](auto&) {
remove_child(*m_notifier);
m_notifier = nullptr;
@ -503,7 +508,7 @@ void Editor::really_quit_event_loop()
m_returned_line = string;
m_notifier->set_event_mask(Core::Notifier::None);
m_notifier->set_enabled(false);
deferred_invoke([this](auto&) {
remove_child(*m_notifier);
m_notifier = nullptr;

View file

@ -39,6 +39,7 @@
#include <AK/Utf8View.h>
#include <AK/Vector.h>
#include <LibCore/DirIterator.h>
#include <LibCore/EventLoop.h>
#include <LibCore/Notifier.h>
#include <LibCore/Object.h>
#include <LibLine/KeyCallbackMachine.h>
@ -74,6 +75,10 @@ struct Configuration {
NoEscapeSequences,
NonInteractive,
};
enum SignalHandler {
WithSignalHandlers,
NoSignalHandlers,
};
Configuration()
{
@ -88,11 +93,13 @@ struct Configuration {
void set(RefreshBehaviour refresh) { refresh_behaviour = refresh; }
void set(OperationMode mode) { operation_mode = mode; }
void set(SignalHandler mode) { m_signal_mode = mode; }
void set(const KeyBinding& binding) { keybindings.append(binding); }
static Configuration from_config(const StringView& libname = "line");
RefreshBehaviour refresh_behaviour { RefreshBehaviour::Lazy };
SignalHandler m_signal_mode { SignalHandler::WithSignalHandlers };
OperationMode operation_mode { OperationMode::Unset };
Vector<KeyBinding> keybindings;
};
@ -180,6 +187,8 @@ public:
m_previous_num_columns = m_num_columns;
get_terminal_size();
m_suggestion_display->set_vt_size(m_num_lines, m_num_columns);
if (m_is_searching)
m_search_editor->resized();
}
size_t cursor() const { return m_cursor; }
@ -321,6 +330,8 @@ private:
ASSERT(m_initialized);
tcsetattr(0, TCSANOW, &m_default_termios);
m_initialized = false;
for (auto id : m_signal_handlers)
Core::EventLoop::unregister_signal(id);
}
const StringMetrics& current_prompt_metrics() const
@ -462,6 +473,7 @@ private:
bool m_initialized { false };
bool m_refresh_needed { false };
Vector<int, 2> m_signal_handlers;
bool m_is_editing { false };

View file

@ -237,7 +237,7 @@ void Editor::enter_search()
// Disable our own notifier so as to avoid interfering with the search editor.
m_notifier->set_enabled(false);
m_search_editor = Editor::construct(Configuration { Configuration::Eager }); // Has anyone seen 'Inception'?
m_search_editor = Editor::construct(Configuration { Configuration::Eager, Configuration::NoSignalHandlers }); // Has anyone seen 'Inception'?
m_search_editor->initialize();
add_child(*m_search_editor);