a632458d8e
* Since the app_server launched the input_server, it would also get notified when the latter died via a signal - but LinkReceiver could return B_INTERRUPTED in that case (it didn't check the return value of port_buffer_size()) which the app_server misinterpreted and quit itself... this fixes the hanging part of bug #1298. * But the input_server still wasn't restarted, because the Registrar had it still listed as being running. Now, the Registrar checks not just periodically for died teams, it will also check for it when a new application registers itself. This fixes the rest of bug #1298. * Removed the old (disabled) R5 style input_server launch mechanism from the app_server. * MessageLooper now prints a bit more information when a port is supposed to have been deleted. * The default implementation of MessageLooper::_GetLooperName() is now returning the name of the semaphore of its BLocker instead of "unnamed looper". git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22115 a95241bf-73f2-0310-859d-f6bbb57e9c96
178 lines
2.9 KiB
C++
178 lines
2.9 KiB
C++
/*
|
|
* Copyright 2005-2007, Haiku.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Axel Dörfler, axeld@pinc-software.de
|
|
*/
|
|
|
|
|
|
#include "MessageLooper.h"
|
|
|
|
#include <Autolock.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
MessageLooper::MessageLooper(const char* name)
|
|
: BLocker(name),
|
|
fThread(-1),
|
|
fQuitting(false),
|
|
fDeathSemaphore(-1)
|
|
{
|
|
}
|
|
|
|
|
|
MessageLooper::~MessageLooper()
|
|
{
|
|
}
|
|
|
|
|
|
bool
|
|
MessageLooper::Run()
|
|
{
|
|
BAutolock locker(this);
|
|
|
|
fQuitting = false;
|
|
|
|
char name[B_OS_NAME_LENGTH];
|
|
_GetLooperName(name, sizeof(name));
|
|
|
|
// Spawn our message-monitoring thread
|
|
fThread = spawn_thread(_message_thread, name, B_DISPLAY_PRIORITY, this);
|
|
if (fThread < B_OK) {
|
|
fQuitting = true;
|
|
return false;
|
|
}
|
|
|
|
if (resume_thread(fThread) != B_OK) {
|
|
fQuitting = true;
|
|
kill_thread(fThread);
|
|
fThread = -1;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void
|
|
MessageLooper::Quit()
|
|
{
|
|
fQuitting = true;
|
|
_PrepareQuit();
|
|
|
|
if (fThread < B_OK) {
|
|
// thread has not been started yet
|
|
delete this;
|
|
return;
|
|
}
|
|
|
|
if (fThread == find_thread(NULL)) {
|
|
// called from our message looper
|
|
delete this;
|
|
exit_thread(0);
|
|
} else {
|
|
// called from a different thread
|
|
PostMessage(kMsgQuitLooper);
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
\brief Send a message to the looper without any attachments
|
|
\param code ID code of the message to post
|
|
*/
|
|
status_t
|
|
MessageLooper::PostMessage(int32 code, bigtime_t timeout)
|
|
{
|
|
BPrivate::LinkSender link(MessagePort());
|
|
link.StartMessage(code);
|
|
return link.Flush(timeout);
|
|
}
|
|
|
|
|
|
/*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;
|
|
}
|
|
|
|
|
|
void
|
|
MessageLooper::_PrepareQuit()
|
|
{
|
|
// to be implemented by subclasses
|
|
}
|
|
|
|
|
|
void
|
|
MessageLooper::_GetLooperName(char* name, size_t length)
|
|
{
|
|
sem_id semaphore = Sem();
|
|
sem_info info;
|
|
if (get_sem_info(semaphore, &info) == B_OK)
|
|
strlcpy(name, info.name, length);
|
|
else
|
|
strlcpy(name, "unnamed looper", length);
|
|
}
|
|
|
|
|
|
void
|
|
MessageLooper::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|
{
|
|
}
|
|
|
|
|
|
void
|
|
MessageLooper::_MessageLooper()
|
|
{
|
|
BPrivate::LinkReceiver& receiver = fLink.Receiver();
|
|
|
|
while (true) {
|
|
int32 code;
|
|
status_t status = receiver.GetNextMessage(code);
|
|
if (status < B_OK) {
|
|
// that shouldn't happen, it's our port
|
|
char name[256];
|
|
_GetLooperName(name, 256);
|
|
printf("MessageLooper \"%s\": Someone deleted our message port %ld, %s!\n",
|
|
name, receiver.Port(), strerror(status));
|
|
break;
|
|
}
|
|
|
|
Lock();
|
|
|
|
if (code == kMsgQuitLooper) {
|
|
Quit();
|
|
} else
|
|
_DispatchMessage(code, receiver);
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
\brief Message-dispatching loop starter
|
|
*/
|
|
/*static*/
|
|
int32
|
|
MessageLooper::_message_thread(void* _looper)
|
|
{
|
|
MessageLooper* looper = (MessageLooper*)_looper;
|
|
|
|
looper->_MessageLooper();
|
|
return 0;
|
|
}
|
|
|