Sfoglia il codice sorgente

WindowServer: Sever the WSWindow/Process link when the process dies.

This fixes a deadlock where the WindowServer would get stuck trying to
acquire a dead process's event stream lock.
Andreas Kling 6 anni fa
parent
commit
0c38a4c30f
4 ha cambiato i file con 25 aggiunte e 6 eliminazioni
  1. 1 0
      Kernel/ProcessGUI.cpp
  2. 4 1
      Kernel/Scheduler.cpp
  3. 15 4
      WindowServer/WSWindow.cpp
  4. 5 1
      WindowServer/WSWindow.h

+ 1 - 0
Kernel/ProcessGUI.cpp

@@ -264,6 +264,7 @@ void Process::destroy_all_windows()
 {
     for (auto& it : m_windows) {
         auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
+        it.value->notify_process_died(Badge<Process>());
         WSMessageLoop::the().post_message(it.value.leak_ptr(), move(message), true);
     }
     m_windows.clear();

+ 4 - 1
Kernel/Scheduler.cpp

@@ -236,7 +236,10 @@ bool Scheduler::context_switch(Process& process)
             current->set_state(Process::Runnable);
 
 #ifdef LOG_EVERY_CONTEXT_SWITCH
-        dbgprintf("Scheduler: %s(%u) -> %s(%u)\n", current->name().characters(), current->pid(), process.name().characters(), process.pid());
+        dbgprintf("Scheduler: %s(%u) -> %s(%u) %w:%x\n",
+                  current->name().characters(), current->pid(),
+                  process.name().characters(), process.pid(),
+                  process.tss().cs, process.tss().eip);
 #endif
     }
 

+ 15 - 4
WindowServer/WSWindow.cpp

@@ -5,7 +5,7 @@
 #include "Process.h"
 
 WSWindow::WSWindow(Process& process, int window_id)
-    : m_process(process)
+    : m_process(&process)
     , m_window_id(window_id)
     , m_pid(process.pid())
 {
@@ -34,11 +34,13 @@ void WSWindow::set_rect(const Rect& rect)
     Rect old_rect;
     {
         WSWindowLocker locker(*this);
+        if (!m_process)
+            return;
         if (m_rect == rect)
             return;
         old_rect = m_rect;
         m_rect = rect;
-        m_backing = GraphicsBitmap::create(m_process, m_rect.size());
+        m_backing = GraphicsBitmap::create(*m_process, m_rect.size());
     }
     WSWindowManager::the().notify_rect_changed(*this, old_rect, rect);
 }
@@ -124,11 +126,20 @@ void WSWindow::on_message(WSMessage& message)
         return;
 
     {
-        LOCKER(m_process.gui_events_lock());
-        m_process.gui_events().append(move(gui_event));
+        WSWindowLocker window_locker(*this);
+        if (!m_process)
+            return;
+        LOCKER(m_process->gui_events_lock());
+        m_process->gui_events().append(move(gui_event));
     }
 }
 
+void WSWindow::notify_process_died(Badge<Process>)
+{
+    WSWindowLocker locker(*this);
+    m_process = nullptr;
+}
+
 void WSWindow::set_global_cursor_tracking_enabled(bool enabled)
 {
     dbgprintf("WSWindow{%p} global_cursor_tracking <- %u\n", enabled);

+ 5 - 1
WindowServer/WSWindow.h

@@ -5,6 +5,8 @@
 #include <AK/AKString.h>
 #include <AK/InlineLinkedList.h>
 #include <AK/Lock.h>
+#include <AK/Badge.h>
+#include <Kernel/Process.h>
 #include "WSMessageReceiver.h"
 
 class Process;
@@ -45,6 +47,8 @@ public:
     void set_global_cursor_tracking_enabled(bool);
     bool global_cursor_tracking() const { return m_global_cursor_tracking_enabled; }
 
+    void notify_process_died(Badge<Process>);
+
     // For InlineLinkedList.
     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
     WSWindow* m_next { nullptr };
@@ -58,7 +62,7 @@ private:
     bool m_global_cursor_tracking_enabled { false };
 
     RetainPtr<GraphicsBitmap> m_backing;
-    Process& m_process;
+    Process* m_process { nullptr };
     int m_window_id { -1 };
     pid_t m_pid { -1 };
 };