servers & kits: Rehabilitate app_server restart functionality.

* It's not really possible to distinguish between a first startup
   and a restart inside app_server itself. Due to the new BServer
   setup, the same port will still be used, too. So, change the
   messages sent to just "AppServerStarted".

 * Since the message is sent out much later than the port is created,
   by the time applications see it, the app_server may have already
   been started a while and applications may have connected to it.
   So, check if we really need to reconnect in BApplication before
   actually trying to do that.

 * BWindow now starts with updates disabled, so they must be
   enabled after reconnecting.

After this commit, basic app_server restart functionality works again;
it's restarted automatically by launch_daemon after dying or being killed
and applications automatically reconnect. However, some problems still
linger (e.g. Terminal doesn't always recreate its windows, colors
on the Desktop look wrong, missing desktop background image, etc.)
This commit is contained in:
Augustin Cavalier
2025-11-18 22:26:31 -05:00
parent fe8f88cff4
commit 49a92384f4
8 changed files with 28 additions and 39 deletions
+1 -2
View File
@@ -13,8 +13,7 @@
#include <Roster.h> #include <Roster.h>
const int32 kMsgAppServerRestarted = 'ASRe'; const int32 kMsgAppServerStarted = '_ASt';
const int32 kMsgRestartAppServer = 'ReAS';
class BRoster::Private { class BRoster::Private {
+8 -2
View File
@@ -691,7 +691,7 @@ BApplication::MessageReceived(BMessage* message)
be_roster->ActivateApp(Team()); be_roster->ActivateApp(Team());
break; break;
case kMsgAppServerRestarted: case kMsgAppServerStarted:
_ReconnectToServer(); _ReconnectToServer();
break; break;
@@ -1454,6 +1454,12 @@ BApplication::_ConnectToServer()
void void
BApplication::_ReconnectToServer() BApplication::_ReconnectToServer()
{ {
team_info dummy;
if (get_team_info(fServerLink->TargetTeam(), &dummy) == B_OK) {
// We're already connected to the correct server.
return;
}
// the sender port belongs to the app_server // the sender port belongs to the app_server
delete_port(fServerLink->ReceiverPort()); delete_port(fServerLink->ReceiverPort());
@@ -1470,7 +1476,7 @@ BApplication::_ReconnectToServer()
if (window == NULL) if (window == NULL)
continue; continue;
BMessenger windowMessenger(window); BMessenger windowMessenger(window);
windowMessenger.SendMessage(kMsgAppServerRestarted); windowMessenger.SendMessage(kMsgAppServerStarted);
} }
reconnect_bitmaps_to_app_server(); reconnect_bitmaps_to_app_server();
+2 -1
View File
@@ -739,7 +739,7 @@ BWindow::MessageReceived(BMessage* message)
if (message->what == B_KEY_DOWN) if (message->what == B_KEY_DOWN)
_KeyboardNavigation(); _KeyboardNavigation();
if (message->what == (int32)kMsgAppServerRestarted) { if (message->what == kMsgAppServerStarted) {
fLink->SetSenderPort( fLink->SetSenderPort(
BApplication::Private::ServerLink()->SenderPort()); BApplication::Private::ServerLink()->SenderPort());
@@ -786,6 +786,7 @@ BWindow::MessageReceived(BMessage* message)
// connect all views to the server again // connect all views to the server again
fTopView->_CreateSelf(); fTopView->_CreateSelf();
EnableUpdates();
_SendShowOrHideMessage(); _SendShowOrHideMessage();
} }
+6 -1
View File
@@ -17,6 +17,7 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <LaunchRoster.h> #include <LaunchRoster.h>
#include <PortLink.h> #include <PortLink.h>
#include <RosterPrivate.h>
#include "BitmapManager.h" #include "BitmapManager.h"
#include "Desktop.h" #include "Desktop.h"
@@ -70,15 +71,19 @@ AppServer::AppServer(status_t* status)
// Create the bitmap allocator. Object declared in BitmapManager.cpp // Create the bitmap allocator. Object declared in BitmapManager.cpp
gBitmapManager = new BitmapManager(); gBitmapManager = new BitmapManager();
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
#if 0 #if 0
// This is not presently needed, as app_server is launched from the login session. // This is not presently needed, as app_server is launched from the login session.
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
// TODO: check the attached displays, and launch login session for them // TODO: check the attached displays, and launch login session for them
BMessage data; BMessage data;
data.AddString("name", "app_server"); data.AddString("name", "app_server");
data.AddInt32("session", 0); data.AddInt32("session", 0);
BLaunchRoster().Target("login", data); BLaunchRoster().Target("login", data);
#endif #endif
// Inform the registrar we've (re)started.
BMessage request(kMsgAppServerStarted);
BRoster::Private().SendTo(&request, NULL, false);
#endif #endif
} }
+2 -1
View File
@@ -582,9 +582,10 @@ InputServer::MessageReceived(BMessage* message)
return; return;
} }
case kMsgAppServerRestarted: case kMsgAppServerStarted:
{ {
BApplication::MessageReceived(message); BApplication::MessageReceived(message);
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
link.StartMessage(AS_REGISTER_INPUT_SERVER); link.StartMessage(AS_REGISTER_INPUT_SERVER);
link.Flush(); link.Flush();
+6 -4
View File
@@ -51,7 +51,7 @@ static const char *kEventQueueName = "timer_thread";
/*! \brief Creates the registrar application class. /*! \brief Creates the registrar application class.
\param error Passed to the BApplication constructor for returning an \param error Passed to the BServer constructor for returning an
error code. error code.
*/ */
Registrar::Registrar(status_t* _error) Registrar::Registrar(status_t* _error)
@@ -375,9 +375,11 @@ Registrar::_MessageReceived(BMessage *message)
} }
break; break;
case kMsgRestartAppServer: case kMsgAppServerStarted:
{ {
fRoster->HandleRestartAppServer(message); fRoster->HandleAppServerStarted(message);
// Don't pass this message on to our BApplication, as that may deadlock.
break; break;
} }
@@ -477,7 +479,7 @@ main()
"registrar main() caught exception: %s", exception.what()); "registrar main() caught exception: %s", exception.what());
debugger(buffer); debugger(buffer);
} catch (...) { } catch (...) {
debugger("registrar main() caught unknown exception"); debugger("registrar main() caught unknown exception");
} }
PRINT("delete app...\n"); PRINT("delete app...\n");
+2 -27
View File
@@ -1141,39 +1141,14 @@ TRoster::HandleSaveRecentLists(BMessage* request)
void void
TRoster::HandleRestartAppServer(BMessage* request) TRoster::HandleAppServerStarted(BMessage* request)
{ {
BAutolock _(fLock); BAutolock _(fLock);
// TODO: if an app_server is still running, stop it first
const char* pathString;
if (request->FindString("path", &pathString) != B_OK)
pathString = "/boot/system/servers";
BPath path(pathString);
path.Append("app_server");
// NOTE: its required at some point that the binary name is "app_server"
const char **argv = new const char * [2];
argv[0] = strdup(path.Path());
argv[1] = NULL;
thread_id threadId = load_image(1, argv, (const char**)environ);
int i;
for (i = 0; i < 1; i++)
delete argv[i];
delete [] argv;
resume_thread(threadId);
// give the server some time to create the server port
snooze(100000);
// notify all apps
// TODO: whats about ourself?
AppInfoListMessagingTargetSet targetSet(fRegisteredApps); AppInfoListMessagingTargetSet targetSet(fRegisteredApps);
if (targetSet.HasNext()) { if (targetSet.HasNext()) {
// send the messages // send the messages
BMessage message(kMsgAppServerRestarted); BMessage message(kMsgAppServerStarted);
MessageDeliverer::Default()->DeliverMessage(&message, targetSet); MessageDeliverer::Default()->DeliverMessage(&message, targetSet);
} }
} }
+1 -1
View File
@@ -56,7 +56,7 @@ public:
void HandleLoadRecentLists(BMessage* request); void HandleLoadRecentLists(BMessage* request);
void HandleSaveRecentLists(BMessage* request); void HandleSaveRecentLists(BMessage* request);
void HandleRestartAppServer(BMessage* request); void HandleAppServerStarted(BMessage* request);
void ClearRecentDocuments(); void ClearRecentDocuments();
void ClearRecentFolders(); void ClearRecentFolders();