git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19599 a95241bf-73f2-0310-859d-f6bbb57e9c96
246 lines
5.7 KiB
C++
246 lines
5.7 KiB
C++
/*
|
|
* Copyright (c) 2005-2006, Haiku, Inc.
|
|
* Distributed under the terms of the MIT license.
|
|
*
|
|
* Author:
|
|
* DarkWyrm <[email protected]>
|
|
*/
|
|
#include "ServicesDaemon.h"
|
|
#include <String.h>
|
|
#include <Alert.h>
|
|
#include <OS.h>
|
|
#include <MediaDefs.h>
|
|
|
|
enum {
|
|
M_RELAUNCH_DESKBAR = 'rtsk',
|
|
M_RELAUNCH_TRACKER,
|
|
M_RELAUNCH_MAIL,
|
|
M_RELAUNCH_PRINT,
|
|
M_RELAUNCH_AUDIO,
|
|
M_RELAUNCH_MEDIA_ADDONS,
|
|
M_RELAUNCH_MEDIA,
|
|
M_RELAUNCH_MIDI
|
|
};
|
|
|
|
// Time delay in microseconds - 2 seconds
|
|
const bigtime_t kRelaunchDelay = 2000000;
|
|
|
|
const char *gSignatures[] = {
|
|
"application/x-vnd.Be-TSKB",
|
|
"application/x-vnd.Be-TRAK",
|
|
"application/x-vnd.Be-POST",
|
|
"application/x-vnd.Be-PSRV",
|
|
"application/x-vnd.Be-AUSV",
|
|
"application/x-vnd.Be.addon-host",
|
|
"application/x-vnd.Be.media-server",
|
|
"application/x-vnd.be-midi-roster",
|
|
NULL
|
|
};
|
|
|
|
static sem_id sRelaunchSem;
|
|
static sem_id sQuitSem;
|
|
|
|
|
|
|
|
App::App(void)
|
|
: BApplication("application/x-vnd.Haiku-ServicesDaemon"),
|
|
fStatus(B_NO_INIT)
|
|
{
|
|
sRelaunchSem = create_sem(1,"relaunch_sem");
|
|
sQuitSem = create_sem(1,"quit_sem");
|
|
|
|
// We will release this when we want the relauncher thread to quit
|
|
acquire_sem(sQuitSem);
|
|
|
|
// We will release this semaphore when we want to activate the relauncher
|
|
// thread
|
|
acquire_sem(sRelaunchSem);
|
|
|
|
fRelauncherID = spawn_thread(App::RelauncherThread, "relauncher_thread",
|
|
B_NORMAL_PRIORITY,this);
|
|
resume_thread(fRelauncherID);
|
|
|
|
fStatus = be_roster->StartWatching(be_app_messenger, B_REQUEST_QUIT);
|
|
if (fStatus != B_OK)
|
|
PostMessage(B_QUIT_REQUESTED);
|
|
}
|
|
|
|
|
|
App::~App(void)
|
|
{
|
|
// Release in this order so that there isn't a race condition when quitting.
|
|
// The thread waits
|
|
release_sem(sQuitSem);
|
|
release_sem(sRelaunchSem);
|
|
|
|
int32 dummyval;
|
|
wait_for_thread(fRelauncherID, &dummyval);
|
|
}
|
|
|
|
|
|
bool
|
|
App::QuitRequested(void)
|
|
{
|
|
if (fStatus == B_OK)
|
|
be_roster->StopWatching(be_app_messenger);
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
App::MessageReceived(BMessage *msg)
|
|
{
|
|
switch (msg->what) {
|
|
case B_SOME_APP_QUIT: {
|
|
BString string;
|
|
if (msg->FindString("be:signature",&string) != B_OK)
|
|
return;
|
|
|
|
int i = 0;
|
|
while (gSignatures[i]) {
|
|
// Checking to see if it's one of the supported signatures
|
|
// and if it is, add a relaunch message to the queue which is
|
|
// to be posted here at the
|
|
if (string.Compare(gSignatures[i]) == 0) {
|
|
BMessage *launchmsg = new BMessage(M_RELAUNCH_DESKBAR + i);
|
|
fRelaunchQueue.AddMessage(launchmsg);
|
|
|
|
release_sem(sRelaunchSem);
|
|
acquire_sem(sRelaunchSem);
|
|
}
|
|
i++;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_DESKBAR: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"The Deskbar is no longer running. Restart it?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
be_roster->Launch(gSignatures[msg->what - M_RELAUNCH_DESKBAR]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_TRACKER: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"Tracker is no longer running. Restart it?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
be_roster->Launch(gSignatures[msg->what - M_RELAUNCH_DESKBAR]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_MAIL: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"Mail services are no longer running. Restart them?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
be_roster->Launch(gSignatures[msg->what - M_RELAUNCH_DESKBAR]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_PRINT: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"Print services are no longer running. Restart them?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
be_roster->Launch(gSignatures[msg->what - M_RELAUNCH_DESKBAR]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_AUDIO: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"The audio server is no longer running. Restart them?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
be_roster->Launch(gSignatures[msg->what - M_RELAUNCH_DESKBAR]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_MEDIA_ADDONS:
|
|
case M_RELAUNCH_MEDIA: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"Media services are no longer running. Restart them?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
shutdown_media_server();
|
|
launch_media_server();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case M_RELAUNCH_MIDI: {
|
|
BAlert *alert = new BAlert("Services Daemon",
|
|
"The MIDI server is no longer running. Restart them?",
|
|
"No","Yes");
|
|
if (alert->Go() == 1) {
|
|
be_roster->Launch(gSignatures[msg->what - M_RELAUNCH_DESKBAR]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
BApplication::MessageReceived(msg);
|
|
}
|
|
}
|
|
|
|
|
|
int32
|
|
App::RelauncherThread(void *data)
|
|
{
|
|
App *app = (App*) data;
|
|
|
|
sem_info quitSemInfo;
|
|
get_sem_info(sQuitSem, &quitSemInfo);
|
|
|
|
while (quitSemInfo.count > -1) {
|
|
// wait until we need to check for a relaunch
|
|
acquire_sem(sRelaunchSem);
|
|
|
|
// We can afford to do this because while we have the semaphore, the
|
|
// app itself is locked.
|
|
BMessage *msg = app->fRelaunchQueue.NextMessage();
|
|
|
|
release_sem(sRelaunchSem);
|
|
|
|
get_sem_info(sQuitSem, &quitSemInfo);
|
|
if (quitSemInfo.count > 0) {
|
|
if (msg)
|
|
delete msg;
|
|
break;
|
|
}
|
|
|
|
if (msg) {
|
|
// Attempt to work around R5 shutdown procedures by checking for
|
|
// debug_server running state. If it's shut down, then chances are that
|
|
// the system is shutting down or has already done so. We use the
|
|
// debug server in particular because it's one of the few services
|
|
// that is available in safe mode which is closed on system shutdown.
|
|
|
|
if (be_roster->IsRunning("application/x-vnd.Be-DBSV")) {
|
|
snooze(kRelaunchDelay);
|
|
app->PostMessage(msg->what);
|
|
delete msg;
|
|
}
|
|
}
|
|
|
|
get_sem_info(sQuitSem, &quitSemInfo);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
App *app = new App();
|
|
app->Run();
|
|
delete app;
|
|
return 0;
|
|
}
|