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
|
\brief Send a message to the looper without any attachments
|
||||||
\param code ID code of the message to post
|
\param code ID code of the message to post
|
||||||
*/
|
*/
|
||||||
void
|
status_t
|
||||||
MessageLooper::PostMessage(int32 code)
|
MessageLooper::PostMessage(int32 code)
|
||||||
{
|
{
|
||||||
BPrivate::LinkSender link(MessagePort());
|
BPrivate::LinkSender link(MessagePort());
|
||||||
link.StartMessage(code);
|
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 bool Run();
|
||||||
virtual void Quit();
|
virtual void Quit();
|
||||||
|
|
||||||
void PostMessage(int32 code);
|
status_t PostMessage(int32 code);
|
||||||
thread_id Thread() const { return fThread; }
|
thread_id Thread() const { return fThread; }
|
||||||
bool IsQuitting() const { return fQuitting; }
|
bool IsQuitting() const { return fQuitting; }
|
||||||
|
sem_id DeathSemaphore() const { return fDeathSemaphore; }
|
||||||
|
|
||||||
virtual port_id MessagePort() const = 0;
|
virtual port_id MessagePort() const = 0;
|
||||||
|
|
||||||
|
static status_t WaitForQuit(sem_id semaphore,
|
||||||
|
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void _PrepareQuit();
|
virtual void _PrepareQuit();
|
||||||
virtual void _GetLooperName(char* name, size_t length);
|
virtual void _GetLooperName(char* name, size_t length);
|
||||||
@@ -41,6 +45,7 @@ class MessageLooper : public BLocker {
|
|||||||
thread_id fThread;
|
thread_id fThread;
|
||||||
BPrivate::PortLink fLink;
|
BPrivate::PortLink fLink;
|
||||||
bool fQuitting;
|
bool fQuitting;
|
||||||
|
sem_id fDeathSemaphore;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int32 kMsgQuitLooper = 'quit';
|
static const int32 kMsgQuitLooper = 'quit';
|
||||||
|
|||||||
@@ -146,51 +146,51 @@ ServerApp::~ServerApp(void)
|
|||||||
if (!fQuitting)
|
if (!fQuitting)
|
||||||
CRITICAL("ServerApp: destructor called after Run()!\n");
|
CRITICAL("ServerApp: destructor called after Run()!\n");
|
||||||
|
|
||||||
fWindowListLock.Lock();
|
|
||||||
|
|
||||||
// quit all server windows
|
// quit all server windows
|
||||||
|
|
||||||
|
fWindowListLock.Lock();
|
||||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||||
ServerWindow* window = fWindowList.ItemAt(i);
|
ServerWindow* window = fWindowList.ItemAt(i);
|
||||||
window->Quit();
|
window->Quit();
|
||||||
}
|
}
|
||||||
int32 tries = fWindowList.CountItems() + 1;
|
|
||||||
|
|
||||||
fWindowListLock.Unlock();
|
fWindowListLock.Unlock();
|
||||||
|
|
||||||
// wait for the windows to quit
|
// 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();
|
fWindowListLock.Unlock();
|
||||||
snooze(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tries < 0) {
|
// wait 3 seconds for our window to quit - that's quite a long
|
||||||
// This really shouldn't happen, as it shows we're buggy
|
// 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__
|
#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
|
#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
|
#endif
|
||||||
|
|
||||||
// there still seem to be some windows left - kill them!
|
// there still seem to be some windows left - kill them!
|
||||||
fWindowListLock.Lock();
|
fWindowListLock.Lock();
|
||||||
|
|
||||||
for (int32 i = 0; i < fWindowList.CountItems(); i++) {
|
for (int32 i = 0; i < fWindowList.CountItems(); i++) {
|
||||||
ServerWindow* window = fWindowList.ItemAt(i);
|
ServerWindow* window = fWindowList.ItemAt(i);
|
||||||
printf("kill window \"%s\"\n", window->Title());
|
printf("kill window \"%s\"\n", window->Title());
|
||||||
|
|
||||||
kill_thread(window->Thread());
|
kill_thread(window->Thread());
|
||||||
window->Hide();
|
window->Hide();
|
||||||
delete window;
|
delete window;
|
||||||
|
}
|
||||||
|
|
||||||
|
fWindowListLock.Unlock();
|
||||||
}
|
}
|
||||||
|
fWindowListLock.Lock();
|
||||||
fWindowListLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// first, make sure our monitor thread doesn't
|
// first, make sure our monitor thread doesn't
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
|
|||||||
looperPort, B_PREFERRED_TOKEN);
|
looperPort, B_PREFERRED_TOKEN);
|
||||||
BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
|
BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
|
||||||
looperPort, clientToken);
|
looperPort, clientToken);
|
||||||
|
|
||||||
|
fDeathSemaphore = create_sem(0, "window death");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,6 +175,8 @@ ServerWindow::~ServerWindow()
|
|||||||
|
|
||||||
delete fDirectWindowData;
|
delete fDirectWindowData;
|
||||||
STRACE(("#ServerWindow(%p) will exit NOW\n", this));
|
STRACE(("#ServerWindow(%p) will exit NOW\n", this));
|
||||||
|
|
||||||
|
delete_sem(fDeathSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user