diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 564ddd25aa..97ca04f29e 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -46,6 +46,7 @@ #include #include +#include //#define DEBUG_SERVERAPP @@ -136,6 +137,48 @@ ServerApp::~ServerApp(void) if (!fQuitting) CRITICAL("ServerApp: destructor called after Run()!\n"); + fWindowListLock.Lock(); + + // quit all server windows + + for (int32 i = fWindowList.CountItems(); i-- > 0;) { + ServerWindow* window = (ServerWindow*)fWindowList.ItemAt(i); + window->Quit(); + } + int32 tries = fWindowList.CountItems() + 1; + + fWindowListLock.Unlock(); + + // wait for the windows to quit + while (tries-- > 0) { + fWindowListLock.Lock(); + if (fWindowList.CountItems() == 0) { + // we leave the list locked, doesn't matter anymore + break; + } + + fWindowListLock.Unlock(); + snooze(10000); + } + + if (tries < 0) { + // This really shouldn't happen, as it shows we're buggy + syslog(LOG_ERR, "ServerApp %s needs to kill some server windows...\n", Signature()); + + // there still seem to be some windows left - kill them! + fWindowListLock.Lock(); + + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + ServerWindow* window = (ServerWindow*)fWindowList.ItemAt(i); + + kill_thread(window->Thread()); + window->Hide(); + delete window; + } + + fWindowListLock.Unlock(); + } + // first, make sure our monitor thread doesn't for (int32 i = 0; i < fBitmapList.CountItems(); i++) { delete static_cast(fBitmapList.ItemAt(i)); diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index b262dfde1e..fc6bb8256c 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -80,6 +80,7 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app, fMessagePort(-1), fClientReplyPort(clientPort), fClientLooperPort(looperPort), + fQuitting(false), fClientViewsWithInvalidCoords(B_VIEW_RESIZED), fHandlerToken(handlerID), fCurrentLayer(NULL) @@ -160,6 +161,8 @@ ServerWindow::Run() void ServerWindow::Quit() { + fQuitting = true; + if (fThread < B_OK) { delete this; return; @@ -170,8 +173,10 @@ ServerWindow::Quit() delete this; exit_thread(0); - } else + } else { + PostMessage(AS_HIDE_WINDOW); PostMessage(kMsgWindowQuit); + } } @@ -206,7 +211,7 @@ ServerWindow::Show() // NOTE: if you do something else, other than sending a port message, PLEASE lock STRACE(("ServerWindow %s: Show\n", Title())); - if (!fWinBorder->IsHidden()) + if (fQuitting || !fWinBorder->IsHidden()) return; fWinBorder->GetRootLayer()->ShowWinBorder(fWinBorder); diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index 8dd31f1fa5..6a6ff850df 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -141,6 +141,7 @@ private: port_id fClientLooperPort; BPrivate::PortLink fLink; + bool fQuitting; BMessage fClientViewsWithInvalidCoords;