WIP draft remainder of the global start/stop sequence, incl errorhandling
This commit is contained in:
parent
01876fd576
commit
75b97ff9dd
8 changed files with 120 additions and 227 deletions
|
|
@ -50,6 +50,9 @@ namespace lumiera {
|
|||
extern Symbol ON_GLOBAL_INIT; ///< to be triggered in main() @note no magic!
|
||||
extern Symbol ON_GLOBAL_SHUTDOWN; ///< to be triggered at the end of main() @note no magic!
|
||||
|
||||
extern Symbol ON_EMERGENCY; ///< activated on shutdown after premature failure of a subsystem
|
||||
|
||||
|
||||
// client code is free to register and use additional lifecycle events
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,20 +35,25 @@ extern "C" {
|
|||
#include "lumiera/plugin.h"
|
||||
}
|
||||
|
||||
//#include "common/util.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "include/configfacade.hpp" //////////TODO: temp hack to force configfacade.o to be linked in
|
||||
|
||||
using util::cStr;
|
||||
|
||||
//using util::isnil;
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
namespace { // implementation details
|
||||
|
||||
inline void
|
||||
log_and_clear_unexpected_errorstate ()
|
||||
{
|
||||
if (const char * errorstate = lumiera_error ())
|
||||
ERROR (NOBUG_ON, "*** Unexpected error: %s\n Triggering emergency exit.", errorstate);
|
||||
} }
|
||||
|
||||
|
||||
Symbol ON_BASIC_INIT ("ON_BASIC_INIT");
|
||||
Symbol ON_GLOBAL_INIT ("ON_GLOBAL_INIT");
|
||||
Symbol ON_GLOBAL_SHUTDOWN ("ON_GLOBAL_SHUTDOWN");
|
||||
|
||||
|
||||
/** perform initialisation triggered on first access.
|
||||
|
|
@ -63,14 +68,13 @@ namespace lumiera {
|
|||
*/
|
||||
AppState::AppState()
|
||||
: lifecycleHooks_(new LifecycleRegistry),
|
||||
parts_(0)
|
||||
subsystems_(0),
|
||||
emergency_(false)
|
||||
{
|
||||
lifecycleHooks_->execute (ON_BASIC_INIT); // note in most cases a NOP
|
||||
}
|
||||
|
||||
|
||||
AppState::~AppState() { }
|
||||
|
||||
|
||||
|
||||
AppState&
|
||||
|
|
@ -93,22 +97,13 @@ namespace lumiera {
|
|||
|
||||
|
||||
|
||||
// ==== implementation startup sequence for main() =======
|
||||
|
||||
struct SubsystemRunner
|
||||
{
|
||||
Option& opts_;
|
||||
|
||||
SubsystemRunner (Option& opts)
|
||||
: opts_(opts)
|
||||
{ }
|
||||
|
||||
};
|
||||
// ===== Implementation startup and shutdown sequence for main() ========
|
||||
|
||||
|
||||
#define _THROW_IF \
|
||||
if (lumiera_error_peek()) \
|
||||
throw error::Fatal (lumiera_error());
|
||||
throw error::Fatal (lumiera_error());
|
||||
|
||||
|
||||
|
||||
|
|
@ -131,16 +126,18 @@ namespace lumiera {
|
|||
_THROW_IF
|
||||
|
||||
|
||||
parts_.reset (new SubsystemRunner (options));
|
||||
subsystems_.reset (new SubsystemRunner (options));
|
||||
TRACE (lumiera, "Lumiera core started successfully.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
AppState::maybeStart (lumiera::Subsys&)
|
||||
AppState::maybeStart (lumiera::Subsys& subsys)
|
||||
{
|
||||
UNIMPLEMENTED ("maybe register and activate the given subsystem");
|
||||
TRACE (lumiera, "maybe startup %s...?", cStr(subsys));
|
||||
ASSERT (subsystems_);
|
||||
subsystems_->maybeRun (subsys);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -148,10 +145,40 @@ namespace lumiera {
|
|||
typedef AppState::ExitCode ExitCode;
|
||||
|
||||
|
||||
/** @par
|
||||
* This function is executed at the end of main(), after the necessary subsystems
|
||||
* have been started, typically in separate threads. Thus, the main thread will
|
||||
* enter a blocking wait, until all activated subsystems have signalled shutdown.
|
||||
* After returning, we can proceed with the normal shutdown sequence.
|
||||
*
|
||||
* The SubsystemRunner ensures that in case of a premature failure of one subsystem,
|
||||
* the termination of all other subsystems is initiated; when detecting this case,
|
||||
* the emergency exit sequence is called. Any error which can't be handled within
|
||||
* this scheme, should be thrown as exception, in which case the abort handler
|
||||
* is activated.
|
||||
*/
|
||||
ExitCode
|
||||
AppState::maybeWait()
|
||||
{
|
||||
UNIMPLEMENTED ("wait on termination and normal shutdown");
|
||||
if (subsystems_)
|
||||
{
|
||||
emergency_ |= subsystems_->wait();
|
||||
subsystems_.reset(0);
|
||||
}
|
||||
|
||||
NOTICE (lumiera, "Shutting down Lumiera...");
|
||||
|
||||
if (emergency_)
|
||||
{
|
||||
ERROR (operate, "Triggering emergency exit...");
|
||||
lifecycle (ON_EMERGENCY);
|
||||
return CLEAN_EMERGENCY_EXIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
lifecycle (ON_GLOBAL_SHUTDOWN);
|
||||
return NORMAL_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -159,23 +186,66 @@ namespace lumiera {
|
|||
ExitCode
|
||||
AppState::abort (lumiera::Error& problem)
|
||||
{
|
||||
|
||||
|
||||
INFO (operate, "Address of Config Facade = %x", &lumiera::Config::instance()); //////////TODO: a temp hack to force configfacade.cpp to be linked into lumiera.exe
|
||||
|
||||
UNIMPLEMENTED ("clean error shutdown");
|
||||
|
||||
ERROR (operate, "Aborting Lumiera after unhandled error: %s", cStr(problem.what()));
|
||||
|
||||
log_and_clear_unexpected_errorstate();
|
||||
|
||||
try
|
||||
{
|
||||
if (subsystems_) subsystems_->shutdownAll();
|
||||
return maybeWait ();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExitCode
|
||||
AppState::abort ()
|
||||
AppState::abort () throw()
|
||||
{
|
||||
UNIMPLEMENTED ("emergency shutdown");
|
||||
log_and_clear_unexpected_errorstate();
|
||||
|
||||
if (emergency_)
|
||||
{
|
||||
lifecycle (ON_EMERGENCY);
|
||||
return FAILED_EMERGENCY_EXIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
lifecycle (ON_GLOBAL_SHUTDOWN);
|
||||
return CLEAN_EXIT_AFTER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** anything which should be closed as late as possible and after
|
||||
* the normal shutdown sequence can be placed into the AppState dtor.
|
||||
* But note though, when the application is halted unconditionally,
|
||||
* not dtors will be executed.
|
||||
*/
|
||||
AppState::~AppState()
|
||||
{
|
||||
try
|
||||
{
|
||||
TRACE (lumiera, "shutting down basic application layer...");
|
||||
lumiera_config_interface_destroy ();
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log_and_clear_unexpected_errorstate();
|
||||
} }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -210,6 +280,13 @@ namespace lumiera {
|
|||
|
||||
|
||||
|
||||
Symbol ON_BASIC_INIT ("ON_BASIC_INIT");
|
||||
Symbol ON_GLOBAL_INIT ("ON_GLOBAL_INIT");
|
||||
Symbol ON_GLOBAL_SHUTDOWN ("ON_GLOBAL_SHUTDOWN");
|
||||
|
||||
Symbol ON_EMERGENCY ("ON_EMERGENCY");
|
||||
|
||||
|
||||
} // namespace lumiera
|
||||
|
||||
|
||||
|
|
@ -220,6 +297,8 @@ extern "C" { /* ==== implementation C interface for lifecycle hooks ======= */
|
|||
extern const char * lumiera_ON_GLOBAL_INIT = lumiera::ON_GLOBAL_INIT;
|
||||
extern const char * lumiera_ON_GLOBAL_SHUTDOWN = lumiera::ON_GLOBAL_SHUTDOWN;
|
||||
|
||||
extern const char * lumiera_ON_EMERGENCY = lumiera::ON_EMERGENCY;
|
||||
|
||||
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace lumiera {
|
|||
private:
|
||||
AppState ();
|
||||
|
||||
~AppState (); ///< deletion prohibited
|
||||
~AppState ();
|
||||
friend void boost::checked_delete<AppState>(AppState*);
|
||||
|
||||
|
||||
|
|
@ -85,8 +85,7 @@ namespace lumiera {
|
|||
|
||||
/** evaluate the result of option parsing and maybe additional configuration
|
||||
* such as to be able to determine the further behaviour of the application.
|
||||
* Set the internal state within this object accordingly.
|
||||
* @return the AppState singleton instance */
|
||||
* Set the internal state within this object accordingly. */
|
||||
void init (lumiera::Option& options);
|
||||
|
||||
|
||||
|
|
@ -119,7 +118,7 @@ namespace lumiera {
|
|||
|
||||
/** initiate an fatal emergency shutdown,
|
||||
* caused by an unforeseen error condition */
|
||||
ExitCode abort ();
|
||||
ExitCode abort () throw();
|
||||
|
||||
|
||||
|
||||
|
|
@ -128,7 +127,9 @@ namespace lumiera {
|
|||
typedef scoped_ptr<SubsystemRunner> PSub;
|
||||
|
||||
PLife lifecycleHooks_;
|
||||
PSub parts_;
|
||||
PSub subsystems_;
|
||||
|
||||
bool emergency_;
|
||||
|
||||
friend class LifecycleHook;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
lumiera.c - Lumiera main application shell
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
//TODO: Support library includes//
|
||||
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
#include "include/nobugcfg.h"
|
||||
#include "lumiera/lumiera.h"
|
||||
#include "lumiera/interface.h"
|
||||
#include "lumiera/interfaceregistry.h"
|
||||
#include "lumiera/plugin.h"
|
||||
|
||||
//TODO: internal/static forward declarations//
|
||||
|
||||
|
||||
//TODO: System includes//
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//code goes here//
|
||||
int
|
||||
start (int argc, char** argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
|
||||
TRACE (lumiera, "initiating shutdown sequence");
|
||||
lumiera_shutdown ();
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
lumiera.h - Lumiera main application shell
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef LUMIERA_LUMIERA_H
|
||||
#define LUMIERA_LUMIERA_H
|
||||
|
||||
//TODO: Support library includes//
|
||||
|
||||
|
||||
//TODO: Forward declarations//
|
||||
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
|
||||
|
||||
//TODO: System includes//
|
||||
#include <nobug.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
|
||||
//TODO: declarations go here//
|
||||
|
||||
void
|
||||
lumiera_shutdown (void);
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
lumiera_init.c - Lumiera initialization and shutdowen and global state
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
//TODO: Support library includes//
|
||||
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
#include "include/nobugcfg.h"
|
||||
#include "lumiera/lumiera.h"
|
||||
#include "lumiera/config_interface.h"
|
||||
|
||||
//TODO: internal/static forward declarations//
|
||||
|
||||
|
||||
//TODO: System includes//
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//code goes here//
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Shutdown procedure
|
||||
* This shuts all subsystem which got initialized in lumiera_init down.
|
||||
* Shutdowns should be arranged in reverse initialization order.
|
||||
*/
|
||||
void
|
||||
lumiera_shutdown (void)
|
||||
{
|
||||
TRACE (lumiera, "shutdown");
|
||||
|
||||
lumiera_config_interface_destroy ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -80,10 +80,10 @@ main (int argc, const char* argv[])
|
|||
|
||||
catch (lumiera::Error& problem)
|
||||
{
|
||||
application.abort (problem);
|
||||
return application.abort (problem);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
application.abort();
|
||||
return application.abort();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ namespace lumiera {
|
|||
triggerStartup (Subsys* susy)
|
||||
{
|
||||
ASSERT (susy);
|
||||
INFO (operate, "Starting subsystem \"%s\"", cStr(*susy));
|
||||
|
||||
for_each (susy->prereq_, start_);
|
||||
bool started = susy.start (opts_, bind (&SubsystemRunner::sigTerm, this, susy, _1));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue