From 04209cdd81e0cc978a5da7a9c9a5175e11b4140c Mon Sep 17 00:00:00 2001 From: czeidler Date: Sun, 22 Jan 2012 14:26:47 +1300 Subject: [PATCH] Catch a app_server crash in the debug server. Let the registrar restart the app_server and notify all apps. --- headers/private/app/RosterPrivate.h | 4 +++ src/servers/debug/DebugServer.cpp | 21 ++++++++++++++- src/servers/registrar/Registrar.cpp | 6 +++++ src/servers/registrar/TRoster.cpp | 40 +++++++++++++++++++++++++++++ src/servers/registrar/TRoster.h | 2 ++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/headers/private/app/RosterPrivate.h b/headers/private/app/RosterPrivate.h index 5674d42a9e..344c5ae705 100644 --- a/headers/private/app/RosterPrivate.h +++ b/headers/private/app/RosterPrivate.h @@ -13,6 +13,10 @@ #include +const int32 kMsgAppServerRestarted = 'ASRe'; +const int32 kMsgRestartAppServer = 'ReAS'; + + class BRoster::Private { public: Private() : fRoster(const_cast(be_roster)) {} diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp index c8a131ea17..28701ce961 100644 --- a/src/servers/debug/DebugServer.cpp +++ b/src/servers/debug/DebugServer.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -865,8 +866,10 @@ TeamDebugHandler::_HandlerThread() kill = true; } + bool isGuiServer = _IsGUIServer(); + // kill the team or hand it over to the debugger - thread_id debuggerThread; + thread_id debuggerThread = -1; if (kill) { // The team shall be killed. Since that is also the handling in case // an error occurs while handing over the team to the debugger, we do @@ -919,6 +922,22 @@ TeamDebugHandler::_HandlerThread() // remove this handler from the roster and delete it TeamDebugHandlerRoster::Default()->RemoveHandler(fTeam); + if (isGuiServer) { + // wait till debugging is done + status_t dummy; + wait_for_thread(debuggerThread, &dummy); + + // find the registrar port + port_id rosterPort = find_port(BPrivate::get_roster_port_name()); + port_info info; + BMessenger messenger; + if (rosterPort >= 0 && get_port_info(rosterPort, &info) == B_OK) { + BMessenger::Private(messenger).SetTo(info.team, rosterPort, + B_PREFERRED_TOKEN); + } + messenger.SendMessage(kMsgRestartAppServer); + } + delete this; return B_OK; diff --git a/src/servers/registrar/Registrar.cpp b/src/servers/registrar/Registrar.cpp index bcd5ef6323..5a54d19b3a 100644 --- a/src/servers/registrar/Registrar.cpp +++ b/src/servers/registrar/Registrar.cpp @@ -350,6 +350,12 @@ Registrar::_MessageReceived(BMessage *message) } break; + case kMsgRestartAppServer: + { + fRoster->HandleRestartAppServer(message); + break; + } + default: BApplication::MessageReceived(message); break; diff --git a/src/servers/registrar/TRoster.cpp b/src/servers/registrar/TRoster.cpp index 31d14bde73..5b34d55b3c 100644 --- a/src/servers/registrar/TRoster.cpp +++ b/src/servers/registrar/TRoster.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1139,6 +1140,45 @@ TRoster::HandleSaveRecentLists(BMessage* request) } +void +TRoster::HandleRestartAppServer(BMessage* request) +{ + 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); + if (targetSet.HasNext()) { + // send the messages + BMessage message(kMsgAppServerRestarted); + MessageDeliverer::Default()->DeliverMessage(&message, targetSet); + } +} + + /*! \brief Clears the current list of recent documents */ void diff --git a/src/servers/registrar/TRoster.h b/src/servers/registrar/TRoster.h index 29c726a453..a9303f7811 100644 --- a/src/servers/registrar/TRoster.h +++ b/src/servers/registrar/TRoster.h @@ -59,6 +59,8 @@ public: void HandleLoadRecentLists(BMessage* request); void HandleSaveRecentLists(BMessage* request); + void HandleRestartAppServer(BMessage* request); + void ClearRecentDocuments(); void ClearRecentFolders(); void ClearRecentApps();