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
This commit is contained in:
Axel Dörfler
2005-11-25 13:49:29 +00:00
parent 85d981378a
commit 67e79bf45a
4 changed files with 54 additions and 29 deletions
+18 -2
View File
@@ -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;
}
+6 -1
View File
@@ -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';
+26 -26
View File
@@ -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
+4
View File
@@ -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);
}