Quellcode durchsuchen

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).
AnotherTest vor 4 Jahren
Ursprung
Commit
9b126a2250
3 geänderte Dateien mit 27 neuen und 10 gelöschten Zeilen
  1. 14 9
      Libraries/LibLine/Editor.cpp
  2. 12 0
      Libraries/LibLine/Editor.h
  3. 1 1
      Libraries/LibLine/InternalFunctions.cpp

+ 14 - 9
Libraries/LibLine/Editor.cpp

@@ -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;

+ 12 - 0
Libraries/LibLine/Editor.h

@@ -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 };
 

+ 1 - 1
Libraries/LibLine/InternalFunctions.cpp

@@ -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);