The wonders of signals:

* 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
This commit is contained in:
Axel Dörfler 2007-08-30 00:09:43 +00:00
parent 25938e2538
commit a632458d8e
7 changed files with 105 additions and 165 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2006, Haiku.
* Copyright 2001-2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -161,11 +161,14 @@ LinkReceiver::AdjustReplyBuffer(bigtime_t timeout)
fRecvBufferSize = kInitialBufferSize;
} else {
STRACE(("info: LinkReceiver getting port_buffer_size().\n"));
ssize_t bufferSize;
if (timeout == B_INFINITE_TIMEOUT)
bufferSize = port_buffer_size(fReceivePort);
else
bufferSize = port_buffer_size_etc(fReceivePort, B_TIMEOUT, timeout);
do {
bufferSize = port_buffer_size_etc(fReceivePort,
timeout == B_INFINITE_TIMEOUT ? B_RELATIVE_TIMEOUT : 0,
timeout);
} while (bufferSize == B_INTERRUPTED);
STRACE(("info: LinkReceiver got port_buffer_size() = %ld.\n", bufferSize));
if (bufferSize < 0)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2006, Haiku, Inc.
* Copyright (c) 2001-2007, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
@ -113,67 +113,6 @@ AppServer::RunLooper()
}
#if 0
/*!
\brief Starts Input Server
*/
void
AppServer::_LaunchInputServer()
{
// We are supposed to start the input_server, but it's a BApplication
// that depends on the registrar running, which is started after app_server
// so we wait on roster thread to launch the input server
fISThreadID = B_ERROR;
while (!BRoster::Private().IsMessengerValid(false) && !fQuitting) {
snooze(250000);
BRoster::Private::DeleteBeRoster();
BRoster::Private::InitBeRoster();
}
if (fQuitting)
return;
// we use an area for cursor data communication with input_server
// area id and sem id are sent to the input_server
if (fCursorArea < B_OK)
fCursorArea = create_area("isCursor", (void**) &fCursorAddr, B_ANY_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
if (fCursorSem < B_OK)
fCursorSem = create_sem(0, "isSem");
int32 arg_c = 1;
char **arg_v = (char **)malloc(sizeof(char *) * (arg_c + 1));
#if TEST_MODE
arg_v[0] = strdup("/boot/home/svnhaiku/trunk/distro/x86.R1/beos/system/servers/input_server");
#else
arg_v[0] = strdup("/system/servers/input_server");
#endif
arg_v[1] = NULL;
fISThreadID = load_image(arg_c, (const char**)arg_v, (const char **)environ);
free(arg_v[0]);
int32 tmpbuf[2] = {fCursorSem, fCursorArea};
int32 code = 0;
send_data(fISThreadID, code, (void *)tmpbuf, sizeof(tmpbuf));
resume_thread(fISThreadID);
setpgid(fISThreadID, 0);
// we receive
thread_id sender;
code = receive_data(&sender, (void *)tmpbuf, sizeof(tmpbuf));
fISASPort = tmpbuf[0];
fISPort = tmpbuf[1];
// if at any time, one of these ports is error prone, it might mean input_server is gone
// then relaunch input_server
}
#endif
/*!
\brief Creates a desktop object for an authorized user
*/
@ -299,12 +238,6 @@ AppServer::_DispatchMessage(int32 code, BPrivate::LinkReceiver& msg)
// #pragma mark -
/*!
\brief Entry function to run the entire server
\param argc Number of command-line arguments present
\param argv String array of the command-line arguments
\return -1 if the app_server is already running, 0 if everything's OK.
*/
int
main(int argc, char** argv)
{

View File

@ -118,7 +118,12 @@ MessageLooper::_PrepareQuit()
void
MessageLooper::_GetLooperName(char* name, size_t length)
{
strcpy(name, "unnamed looper");
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);
}
@ -138,7 +143,10 @@ MessageLooper::_MessageLooper()
status_t status = receiver.GetNextMessage(code);
if (status < B_OK) {
// that shouldn't happen, it's our port
printf("Someone deleted our message port!\n");
char name[256];
_GetLooperName(name, 256);
printf("MessageLooper \"%s\": Someone deleted our message port %ld, %s!\n",
name, receiver.Port(), strerror(status));
break;
}

View File

@ -1,63 +1,46 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: RosterAppInfo.cpp
// Author: Ingo Weinhold (bonefish@users.sf.net)
// Description: An extended app_info.
//------------------------------------------------------------------------------
/*
* Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#include <new>
#include <string.h>
//! An extended app_info.
#include "RosterAppInfo.h"
#include <new>
#include <string.h>
using std::nothrow;
// constructor
RosterAppInfo::RosterAppInfo()
: app_info(),
state(APP_STATE_UNREGISTERED),
token(0),
registration_time(0)
: app_info(),
state(APP_STATE_UNREGISTERED),
token(0),
registration_time(0)
{
}
// Init
void
RosterAppInfo::Init(thread_id thread, team_id team, port_id port, uint32 flags,
const entry_ref *ref, const char *signature)
const entry_ref *ref, const char *signature)
{
this->thread = thread;
this->team = team;
this->port = port;
this->flags = flags;
this->ref = *ref;
if (signature) {
strncpy(this->signature, signature, B_MIME_TYPE_LENGTH - 1);
this->signature[B_MIME_TYPE_LENGTH - 1] = '\0';
} else
if (signature)
strlcpy(this->signature, signature, B_MIME_TYPE_LENGTH);
else
this->signature[0] = '\0';
}
// Clone
RosterAppInfo *
RosterAppInfo::Clone() const
@ -70,3 +53,13 @@ RosterAppInfo::Clone() const
clone->registration_time = registration_time;
return clone;
}
// IsRunning
bool
RosterAppInfo::IsRunning() const
{
team_info teamInfo;
return get_team_info(team, &teamInfo) == B_OK;
}

View File

@ -1,29 +1,7 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: RosterAppInfo.h
// Author: Ingo Weinhold (bonefish@users.sf.net)
// Description: An extended app_info.
//------------------------------------------------------------------------------
/*
* Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#ifndef ROSTER_APP_INFO_H
#define ROSTER_APP_INFO_H
@ -45,9 +23,10 @@ struct RosterAppInfo : app_info {
RosterAppInfo();
void Init(thread_id thread, team_id team, port_id port, uint32 flags,
const entry_ref *ref, const char *signature);
const entry_ref *ref, const char *signature);
RosterAppInfo *Clone() const;
bool IsRunning() const;
};
#endif // ROSTER_APP_INFO_H

View File

@ -179,24 +179,26 @@ PRINT(("full registration: %d\n", fullReg));
uint32 token = 0;
uint32 launchFlags = flags & B_LAUNCH_MASK;
BEntry entry(&ref);
if (!entry.Exists())
SET_ERROR(error, B_ENTRY_NOT_FOUND);
if (error == B_OK)
_ValidateRunning(ref, signature);
// entry_ref
if (error == B_OK) {
// the entry_ref must be valid
if (BEntry(&ref).Exists()) {
PRINT(("flags: %lx\n", flags));
PRINT(("ref: %ld, %lld, %s\n", ref.device, ref.directory, ref.name));
// check single/exclusive launchers
RosterAppInfo *info = NULL;
if ((launchFlags == B_SINGLE_LAUNCH
|| launchFlags == B_EXCLUSIVE_LAUNCH)
&& (((info = fRegisteredApps.InfoFor(&ref)))
|| ((info = fEarlyPreRegisteredApps.InfoFor(&ref))))) {
SET_ERROR(error, B_ALREADY_RUNNING);
otherTeam = info->team;
}
} else
SET_ERROR(error, B_ENTRY_NOT_FOUND);
// check single/exclusive launchers
RosterAppInfo *info = NULL;
if ((launchFlags == B_SINGLE_LAUNCH
|| launchFlags == B_EXCLUSIVE_LAUNCH)
&& ((info = info = fRegisteredApps.InfoFor(&ref)) != NULL
|| (info = fEarlyPreRegisteredApps.InfoFor(&ref)) != NULL)) {
SET_ERROR(error, B_ALREADY_RUNNING);
otherTeam = info->team;
}
}
// signature
@ -1274,8 +1276,7 @@ TRoster::CheckSanity()
// not early (pre-)registered applications
AppInfoList obsoleteApps;
for (AppInfoList::Iterator it = fRegisteredApps.It(); it.IsValid(); ++it) {
team_info teamInfo;
if (get_team_info((*it)->team, &teamInfo) != B_OK)
if (!(*it)->IsRunning())
obsoleteApps.AddInfo(*it);
}
// remove the apps
@ -1750,7 +1751,30 @@ TRoster::_HandleGetRecentEntries(BMessage *request)
FUNCTION_END();
}
// _IsSystemApp
/*!
\brief Checks all registered apps for \a ref and \a signature if
they are still alive, and removes those that aren't.
*/
void
TRoster::_ValidateRunning(const entry_ref& ref, const char* signature)
{
while (true) {
// get info via ref or signature
RosterAppInfo* info = fRegisteredApps.InfoFor(&ref);
if (info == NULL && signature != NULL)
info = fRegisteredApps.InfoFor(signature);
// if app is alive or does not exist, we can exit
if (info == NULL || info->IsRunning())
return;
RemoveApp(info);
delete info;
}
}
bool
TRoster::_IsSystemApp(RosterAppInfo *info) const
{

View File

@ -84,20 +84,20 @@ private:
void _AppDeactivated(RosterAppInfo *info);
// helper functions
static status_t _AddMessageAppInfo(BMessage *message,
const app_info *info);
static status_t _AddMessageWatchingInfo(BMessage *message,
const app_info *info);
static status_t _AddMessageAppInfo(BMessage* message, const app_info* info);
static status_t _AddMessageWatchingInfo(BMessage* message,
const app_info* info);
uint32 _NextToken();
void _AddIARRequest(IARRequestMap& map, int32 key, BMessage* request);
void _ReplyToIARRequests(BMessageQueue *requests,
const RosterAppInfo *info);
void _ReplyToIARRequest(BMessage *request, const RosterAppInfo *info);
void _ReplyToIARRequests(BMessageQueue* requests,
const RosterAppInfo* info);
void _ReplyToIARRequest(BMessage* request, const RosterAppInfo* info);
void _HandleGetRecentEntries(BMessage *request);
void _HandleGetRecentEntries(BMessage* request);
bool _IsSystemApp(RosterAppInfo *info) const;
void _ValidateRunning(const entry_ref& ref, const char* signature);
bool _IsSystemApp(RosterAppInfo* info) const;
status_t _LoadRosterSettings(const char *path = NULL);
status_t _SaveRosterSettings(const char *path = NULL);
@ -109,7 +109,7 @@ private:
AppInfoList fEarlyPreRegisteredApps;
IARRequestMap fIARRequestsByID;
IARRequestMap fIARRequestsByToken;
RosterAppInfo *fActiveApp;
RosterAppInfo* fActiveApp;
WatchingService fWatchingService;
RecentApps fRecentApps;
RecentEntries fRecentDocuments;