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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user