From 67e79bf45aca758085d8272ba2c2c46415560361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 25 Nov 2005 13:49:29 +0000 Subject: [PATCH] A message looper can now have a death semaphore, ServerWindow now uses them. ServerApp now waits up to 3 seconds for windows before killing them - it now waits on the death semaphore, and only kills a window if it didn't quit fast enough. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15147 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/MessageLooper.cpp | 20 ++++++++++-- src/servers/app/MessageLooper.h | 7 ++++- src/servers/app/ServerApp.cpp | 52 +++++++++++++++---------------- src/servers/app/ServerWindow.cpp | 4 +++ 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/servers/app/MessageLooper.cpp b/src/servers/app/MessageLooper.cpp index 5671c56b71..1bb483c2e7 100644 --- a/src/servers/app/MessageLooper.cpp +++ b/src/servers/app/MessageLooper.cpp @@ -81,12 +81,28 @@ MessageLooper::Quit() \brief Send a message to the looper without any attachments \param code ID code of the message to post */ -void +status_t MessageLooper::PostMessage(int32 code) { BPrivate::LinkSender link(MessagePort()); link.StartMessage(code); - link.Flush(); + return link.Flush(); +} + + +/*static*/ +status_t +MessageLooper::WaitForQuit(sem_id semaphore, bigtime_t timeout) +{ + status_t status; + do { + status = acquire_sem_etc(semaphore, 1, B_RELATIVE_TIMEOUT, timeout); + } while (status == B_INTERRUPTED); + + if (status == B_TIMED_OUT) + return status; + + return B_OK; } diff --git a/src/servers/app/MessageLooper.h b/src/servers/app/MessageLooper.h index 4c5c1371aa..ec0cc67103 100644 --- a/src/servers/app/MessageLooper.h +++ b/src/servers/app/MessageLooper.h @@ -22,12 +22,16 @@ class MessageLooper : public BLocker { virtual bool Run(); virtual void Quit(); - void PostMessage(int32 code); + status_t PostMessage(int32 code); thread_id Thread() const { return fThread; } bool IsQuitting() const { return fQuitting; } + sem_id DeathSemaphore() const { return fDeathSemaphore; } virtual port_id MessagePort() const = 0; + static status_t WaitForQuit(sem_id semaphore, + bigtime_t timeout = B_INFINITE_TIMEOUT); + private: virtual void _PrepareQuit(); virtual void _GetLooperName(char* name, size_t length); @@ -41,6 +45,7 @@ class MessageLooper : public BLocker { thread_id fThread; BPrivate::PortLink fLink; bool fQuitting; + sem_id fDeathSemaphore; }; static const int32 kMsgQuitLooper = 'quit'; diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index d140afeb88..978ca3ceba 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -146,51 +146,51 @@ ServerApp::~ServerApp(void) if (!fQuitting) CRITICAL("ServerApp: destructor called after Run()!\n"); - fWindowListLock.Lock(); - // quit all server windows + fWindowListLock.Lock(); for (int32 i = fWindowList.CountItems(); i-- > 0;) { ServerWindow* window = 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; - } + snooze(20000); + + fWindowListLock.Lock(); + for (int32 i = fWindowList.CountItems(); i-- > 0;) { + sem_id deathSemaphore = fWindowList.ItemAt(i)->DeathSemaphore(); fWindowListLock.Unlock(); - snooze(10000); - } - if (tries < 0) { - // This really shouldn't happen, as it shows we're buggy + // wait 3 seconds for our window to quit - that's quite a long + // time, but killing it might have desastrous effects + if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) { + // This really shouldn't happen, as it shows we're buggy #if __HAIKU__ - syslog(LOG_ERR, "ServerApp %s needs to kill some server windows...\n", Signature()); + syslog(LOG_ERR, "ServerApp %s needs to kill some server windows!\n", + Signature()); #else - fprintf(stderr, "ServerApp %s needs to kill some server windows...\n", Signature()); + printf("ServerApp %s needs to kill some server windows!\n", + Signature()); #endif - // there still seem to be some windows left - kill them! - fWindowListLock.Lock(); + // there still seem to be some windows left - kill them! + fWindowListLock.Lock(); - for (int32 i = 0; i < fWindowList.CountItems(); i++) { - ServerWindow* window = fWindowList.ItemAt(i); - printf("kill window \"%s\"\n", window->Title()); + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + ServerWindow* window = fWindowList.ItemAt(i); + printf("kill window \"%s\"\n", window->Title()); - kill_thread(window->Thread()); - window->Hide(); - delete window; + kill_thread(window->Thread()); + window->Hide(); + delete window; + } + + fWindowListLock.Unlock(); } - - fWindowListLock.Unlock(); + fWindowListLock.Lock(); } // first, make sure our monitor thread doesn't diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index b107ce8eae..adcc709a70 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -153,6 +153,8 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app, looperPort, B_PREFERRED_TOKEN); BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam, looperPort, clientToken); + + fDeathSemaphore = create_sem(0, "window death"); } @@ -173,6 +175,8 @@ ServerWindow::~ServerWindow() delete fDirectWindowData; STRACE(("#ServerWindow(%p) will exit NOW\n", this)); + + delete_sem(fDeathSemaphore); }