SlideShare ist ein Scribd-Unternehmen logo
1 von 52
Downloaden Sie, um offline zu lesen
Dive into SObjectizer-5.5
SObjectizer Team, Jan 2016
Fourth Part: Exceptions
(at v.5.5.15)
This is the next part of the series of presentations with deep
introduction into features of SObjectizer-5.5.
This part is dedicated to usage of exceptions. In particular:
● why exceptions are used in SObjectizer Run-Time;
● what exceptions are used by SObjectizer-5;
● how SObjectizer-5.5 handles exceptions from agents;
● how a custom exception logger could be set;
● when and why SObjectizer can call std::abort().
SObjectizer Team, Jan 2016
Why SObjectizer Run-Time Uses Exceptions
SObjectizer Team, Jan 2016
Exceptions are the primary way of error reporting in
SObjectizer-5.
There are no methods/functions which use return codes for
indication of success or failure. Any method/function either
finishes successfully or throws an exception.
If a user does a valid call and here are all necessary
resources (like RAM, OS threads and so on) then there is no
source for a failure...
SObjectizer Team, Jan 2016
...but if something goes wrong (like insufficient amount of
RAM or inability to start yet another OS thread) then
returning an error code as indication of failure is not a good
idea.
SObjectizer Team, Jan 2016
Heavy usage of exceptions is a consequence of experience
from several years with SObjectizer-4 in production.
Error codes were used in SObjectizer-4. And the main
lesson learned was:
If an error handling could be forgotten then
it will be forgotten.
SObjectizer Team, Jan 2016
The most unpleasant error in SObjectizer-4 was
unsuccessful subscription.
If a subscription failed but error is not handled then the work
of an agent will be continued.
But the agent will work incorrectly.
And it could take a long time before the incorrectness will be
found and fixed.
SObjectizer Team, Jan 2016
The main purpose of exceptions in SObjectizer-5 is to
prevent the disregard of errors.
Ignoring error code is easier than ignoring of an exception.
Because of that all methods/functions like creating coops or
subscribing of events throw exceptions in the case of error.
SObjectizer Team, Jan 2016
More than four years of working with SObjectizer-5 show
that SObjectizer-related exceptions are not an issue.
Just because they are thrown when a programmer does
something wrong.
It is hard to get SObjectizer-5 to throw an exception in
normal situation...
SObjectizer Team, Jan 2016
For example, if agent creates a legal subscription for existing
mbox there is no reason for exception…
...except the case of lack of memory.
But in this particular case it is better to throw an exception
instead of сontinuation of execution without subscription
made or abortion of a whole application.
That is why SObjectizer-5.5 uses exceptions instead of error
codes.
SObjectizer Team, Jan 2016
If you do not like exceptions and prefer dealing with error
code in plain-old-C-style...
SObjectizer Team, Jan 2016
If you do not like exceptions and prefer dealing with error
code in plain-old-C-style...
Then you probably is trying to use
an inappropriate framework.
It seems that SObjectizer-5 is a wrong choice for you.
Just try to find something else.
SObjectizer Team, Jan 2016
What Exceptions Are Used By SObjectizer?
SObjectizer Team, Jan 2016
SObjectizer-5 doesn’t use a complex hierarchy of exception
classes.
There is only one class for representing SObjectizer-related
exceptions: so_5::exception_t.
It is derived from std::runtime_error.
SObjectizer Team, Jan 2016
Method exception_t::what(), inherited from
std::exception, returns textual description of an error.
But there is exception_t::error_code() method which returns
internal error code represented as int.
All SObjectizer error codes are defined inside so_5
namespace as constants with prefix rc_ in their names:
rc_disp_start_failed, rc_parent_coop_not_found and so on.
SObjectizer Team, Jan 2016
So if it is necessary to catch, analyze and handle
SObjectizer-related exception it could be done like that:
try
{
... // Some action with SObjectizer.
}
catch( const so_5::exception_t & x )
{
if( so_5::rc_named_disp_not_found == x.error_code() )
... // Create named dispatcher and try again.
else
throw;
}
SObjectizer Team, Jan 2016
Exceptions From Agents
SObjectizer Team, Jan 2016
There is one simple rule:
Normal agents should provide no-throw guarantee!
SObjectizer Team, Jan 2016
It means that an exception should not go out of an event-
handler.
It is because SObjectizer doesn’t know what to do with that
exception.
And doesn’t know the actual state of agent: is the agent in
the correct state and could process next message or the
agent’s internals are broken and no more messages must be
delivered to the agent.
SObjectizer Team, Jan 2016
So the best way is to catch and handle all exception inside
an agent’s event-handler.
But what if an exception is going out anyway?
SObjectizer Team, Jan 2016
When SObjectizer detects an exception of type
std::exception (or derived from it) the following actions are
performed:
● the exception caught is logged by a special exception
logger (more about it below);
● virtual method so_exception_reaction() is called for the
agent who threw the exception;
● perform action(s) in dependence of
so_exception_reaction() result.
SObjectizer Team, Jan 2016
Virtual method so_exception_reaction() can return one of the
following values...
SObjectizer Team, Jan 2016
so_5::abort_on_exception
This value means that the whole application must be terminated
immediately by calling std::abort().
SObjectizer Team, Jan 2016
so_5::shutdown_sobjectizer_on_exception
This value means that:
● the agent who threw the exception will be switched to a special
state (in that state it cannot handle other messages);
● SObjectizer Environment in which the exception has been
caught will be shutdowned the usual way.
This value useful if agent provides basic exception guarantee (no
resources leaks) and application can be shutdowned normally.
SObjectizer Team, Jan 2016
so_5::deregister_coop_on_exception
This value means that:
● the agent who threw the exception will be switched to a special
state (in that state it cannot handle other messages);
● the coop which holds the problematic agent will be
deregistered.
This value useful if agent provides basic exception guarantee (no
resources leaks) and application can continue its work after
deregistration of that coop. For example, the coop will be
automatically registered again by some supervisor.
SObjectizer Team, Jan 2016
so_5::ignore_exception
This value means that no more actions should be performed by
SObjectizer.
This value is useful if agent provides strong exception guarantee.
SObjectizer assumes that no damage has been made and work
could be safely continued.
SObjectizer Team, Jan 2016
so_5::inherit_exception_reaction
This value means that actual exception reaction needs to be
received from agent’s coop.
SObjectizer call exception_reaction() method for agent’s coop.
One of the values described above could be received. The
appropriate action will be performed.
SObjectizer Team, Jan 2016
But the value so_5::inherit_exception_reaction could be
returned by coop_t::exception_reaction() method.
In that case SObjectizer will call exception_reaction() method for
the parent coop (if exists). And then for the parent of the parent
and so on.
If the top-most parent coop returns inherit_exception_reaction then
exception_reaction() method will be called for SObjectizer
Exception instance. That method usually returns
abort_on_exception.
SObjectizer Team, Jan 2016
By default agent_t::so_exception_reaction() and coop_t::
exception_reaction() return inherit_exception_reaction value.
By default environment_t::exception_reaction() return
abort_on_exception.
So the application will be aborted in the case of an uncaught
exception by default.
SObjectizer Team, Jan 2016
A user can set appropriate exception reaction for the whole
coop by coop_t::set_exception_reaction() method:
env.introduce_coop( []( so_5::coop_t & coop ) {
coop.set_exception_reaction( so_5::deregister_coop_on_exception );
...
} );
In that case an exception from any coop’s agent will lead to
deregistration of the coop (but only if agent’s
so_exception_reaction() returns inherit_exception_reaction
value).
SObjectizer Team, Jan 2016
An exception reaction for the whole SObjectizer Environment
can be set via Environment’s parameters:
so_5::launch( []( so_5::environment_t & env ) {
... // Starting code.
},
[]( so_5::environment_params_t & params ) {
... // Environment parameters tuning code.
// Setting the exception reaction for the whole Environment.
params.exception_reaction( so_5::shutdown_sobjectizer_on_exception );
} );
SObjectizer Team, Jan 2016
Coop Dereg Reason
SObjectizer Team, Jan 2016
There is a possibility to know what the reason was behind
the coop deregistration.
When a coop is deregistered a special value must be passed
to environment_t::deregister_coop(). This value is a “coop
dereg reason”.
There are several predefined values which are defined as
constants in so_5::dereg_reason namespace...
SObjectizer Team, Jan 2016
● normal. Coop’s deregistration is a part of application
logic;
● shutdown. Deregistration is a part of Environment’s
shutdown process;
● parent_deregistration. Coop is deregistered because its
parent coop is deregistered.
● unhandled_exception. Coop is deregistered because of
unhandled exception.
There are several additional constants but they intended for
use by a programmer, not SObjectizer.
SObjectizer Team, Jan 2016
Coop dereg reason is passed to coop dereg notificator.
So a notificator can use this value for performing some
actions.
For example for restarting a cooperation in the case of
exception...
SObjectizer Team, Jan 2016
Restart coop on exception example (1/3):
#include <iostream>
#include <so_5/all.hpp>
void start_coop( so_5::environment_t & env )
{
env.introduce_coop( [&]( so_5::coop_t & coop ) {
struct raise_exception : public so_5::signal_t {};
// The single agent of the coop.
// Will throw an exception after one second from registration.
auto agent = coop.define_agent();
agent.on_start( [agent] {
so_5::send_delayed< raise_exception >( agent, std::chrono::seconds(1) );
} )
.event< raise_exception >( agent, [] {
throw std::runtime_error( "Just a test exception" );
} );
SObjectizer Team, Jan 2016
Restart coop on exception example (2/3):
// Tell SObjectizer to deregister the coop on exception.
coop.set_exception_reaction( so_5::deregister_coop_on_exception );
// Add notificator which will initiate reregistration of the coop.
coop.add_dereg_notificator(
[]( so_5::environment_t & env,
const std::string & coop_name,
const so_5::coop_dereg_reason_t & why )
{
std::cout << "Deregistered: " << coop_name << ", reason: "
<< why.reason() << std::endl;
if( so_5::dereg_reason::unhandled_exception == why.reason() )
start_coop( env );
} );
} );
}
SObjectizer Team, Jan 2016
Restart coop on exception example (3/3):
int main()
{
so_5::launch( []( so_5::environment_t & env ) {
// Register coop the first time.
start_coop( env );
// Take some time to the example to work.
std::this_thread::sleep_for( std::chrono::seconds( 5 ) );
env.stop();
} );
}
SObjectizer Team, Jan 2016
Custom Exception Logger
SObjectizer Team, Jan 2016
Every unhandled exception is logged.
Default exception logger uses std::cerr as an output stream.
A user can set its own custom exception logger.
SObjectizer Team, Jan 2016
An exception logger must be derived from class
so_5::event_exception_logger_t.
At least one method, log_exception(), must be overridden
and implemented.
It could looks like...
SObjectizer Team, Jan 2016
A very simple implementation of event_exception_logger_t:
class spd_exception_logger : public so_5::event_exception_logger_t
{
public :
spd_exception_logger()
: logger_( spdlog::rotating_logger_mt( "file_logger",
"logs/exceptions", 10*1024*1024 ) )
{}
virtual void log_exception( const std::exception & ex, const std::string & coop_name ) override
{
logger_->alert( "Unhandled exception from coop '{}': {}", coop_name, ex.what() );
}
private :
std::shared_ptr< spdlog::logger > logger_;
};
SObjectizer Team, Jan 2016
There are two ways to set up a custom exception logger...
SObjectizer Team, Jan 2016
The first one is usage of Environment parameters:
so_5::launch( []( so_5::environment_t & env ) {
... // Starting code.
},
[]( so_5::environment_params_t & params ) {
... // Environment parameters tuning code.
// Setting the exception logger.
params.event_exception_logger(
so_5::event_exception_logger_unique_ptr_t{new spd_exception_logger{}} );
} );
SObjectizer Team, Jan 2016
The second one is usage of Environment’s
install_exception_logger() method:
so_5::launch( []( so_5::environment_t & env ) {
env.install_exception_logger(
so_5::event_exception_logger_unique_ptr_t{
new spd_exception_logger{} } );
... // Starting code.
} );
The main difference between those approaches is the ability
to change exception logger on working Environment via
install_exception_logger() method.
SObjectizer Team, Jan 2016
When and why SObjectizer calls std::abort()?
SObjectizer Team, Jan 2016
There are some situations where SObjectizer cannot throw
an exception and has to call abort() instead.
SObjectizer Team, Jan 2016
One of them is nested exceptions during handling an
uncaught exception from some agent’s event handler.
For example:
● SObjectizer calls log_exception() method for custom exception
logger;
● log_exception() throws an exception;
● SObjectizer calls abort().
SObjectizer Team, Jan 2016
Another one is related to delayed and periodic messages. If
the timer thread can’t send a message instance then abort()
will be called.
It is because inability to send a delayed/periodic message is a
violation of an important contract: if delayed/periodic message was
successfully scheduled then it must be sent.
There is no other way to report a violation of that contract except
calling the abort() function.
SObjectizer Team, Jan 2016
There are some other situations when SObjectizer calls
abort(). They are related to problems during recovery from
some previous errors.
There is a possibility of errors during registration of some coop. An
attempt to create another working thread in a dispatcher can fail.
SObjectizer will revert all changes which have been made before
that failure.
If some exception is thrown during this recovery SObjectizer has
no choice except to call abort().
SObjectizer Team, Jan 2016
So there are places in the SObjectizer code where abort() is
called.
But abort() is called by SObjectizer only in the case of a very
serious problem. When there is no other way to continue
correct work of an application.
SObjectizer Team, Jan 2016
Additional Information:
Project’s home: http://sourceforge.net/projects/sobjectizer
Documentation: http://sourceforge.net/p/sobjectizer/wiki/
Forum: http://sourceforge.net/p/sobjectizer/discussion/
Google-group: https://groups.google.com/forum/#!forum/sobjectizer
GitHub mirror: https://github.com/masterspline/SObjectizer

Más contenido relacionado

Was ist angesagt?

arataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world examplearataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world exampleYauheni Akhotnikau
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentArtur Szott
 
Redux Thunk - Fu - Fighting with Async
Redux Thunk - Fu - Fighting with AsyncRedux Thunk - Fu - Fighting with Async
Redux Thunk - Fu - Fighting with AsyncArtur Szott
 
React.js enlightenment
React.js enlightenmentReact.js enlightenment
React.js enlightenmentArtur Szott
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckAndrey Karpov
 
10 Typical Problems in Enterprise Java Applications
10 Typical Problems in Enterprise Java Applications10 Typical Problems in Enterprise Java Applications
10 Typical Problems in Enterprise Java ApplicationsEberhard Wolff
 
Analysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSAnalysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSPVS-Studio
 
Exception handling
Exception handlingException handling
Exception handlingIblesoft
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionDinesh Sharma
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkMicha Kops
 
Behavioral pattern 4
Behavioral pattern 4Behavioral pattern 4
Behavioral pattern 4Naga Muruga
 
Still Comparing "this" Pointer to Null?
Still Comparing "this" Pointer to Null?Still Comparing "this" Pointer to Null?
Still Comparing "this" Pointer to Null?Andrey Karpov
 
Mvc interview questions – deep dive jinal desai
Mvc interview questions – deep dive   jinal desaiMvc interview questions – deep dive   jinal desai
Mvc interview questions – deep dive jinal desaijinaldesailive
 

Was ist angesagt? (20)

What is SObjectizer 5.5
What is SObjectizer 5.5What is SObjectizer 5.5
What is SObjectizer 5.5
 
arataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world examplearataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world example
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
 
Redux Thunk - Fu - Fighting with Async
Redux Thunk - Fu - Fighting with AsyncRedux Thunk - Fu - Fighting with Async
Redux Thunk - Fu - Fighting with Async
 
React.js enlightenment
React.js enlightenmentReact.js enlightenment
React.js enlightenment
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd Check
 
Mockito intro
Mockito introMockito intro
Mockito intro
 
EasyMock for Java
EasyMock for JavaEasyMock for Java
EasyMock for Java
 
Bot builder v4 HOL
Bot builder v4 HOLBot builder v4 HOL
Bot builder v4 HOL
 
10 Typical Problems in Enterprise Java Applications
10 Typical Problems in Enterprise Java Applications10 Typical Problems in Enterprise Java Applications
10 Typical Problems in Enterprise Java Applications
 
Analysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMSAnalysis of bugs in Orchard CMS
Analysis of bugs in Orchard CMS
 
Exception handling
Exception handlingException handling
Exception handling
 
Spring AOP
Spring AOPSpring AOP
Spring AOP
 
Use me strict
Use me strictUse me strict
Use me strict
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency Injection
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured framework
 
Behavioral pattern 4
Behavioral pattern 4Behavioral pattern 4
Behavioral pattern 4
 
Exception
ExceptionException
Exception
 
Still Comparing "this" Pointer to Null?
Still Comparing "this" Pointer to Null?Still Comparing "this" Pointer to Null?
Still Comparing "this" Pointer to Null?
 
Mvc interview questions – deep dive jinal desai
Mvc interview questions – deep dive   jinal desaiMvc interview questions – deep dive   jinal desai
Mvc interview questions – deep dive jinal desai
 

Ähnlich wie Dive into SObjectizer 5.5. Fourth part. Exception

What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)Yauheni Akhotnikau
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)Yauheni Akhotnikau
 
Static analysis and ROI
Static analysis and ROIStatic analysis and ROI
Static analysis and ROIAndrey Karpov
 
Static analysis and ROI
Static analysis and ROIStatic analysis and ROI
Static analysis and ROIPVS-Studio
 
Exception Handling in UiPath.pptx
Exception Handling in UiPath.pptxException Handling in UiPath.pptx
Exception Handling in UiPath.pptxApurbaSamanta9
 
IRJET- Technique of Finding the Defect in Software Testing
IRJET- Technique of Finding the Defect in Software TestingIRJET- Technique of Finding the Defect in Software Testing
IRJET- Technique of Finding the Defect in Software TestingIRJET Journal
 
QA Best Practices
QA  Best PracticesQA  Best Practices
QA Best PracticesJames York
 
Certification preparation - Error Handling and Troubleshooting recap.pptx
Certification preparation - Error Handling and Troubleshooting recap.pptxCertification preparation - Error Handling and Troubleshooting recap.pptx
Certification preparation - Error Handling and Troubleshooting recap.pptxRohit Radhakrishnan
 
Abapdebuggingfrombasictoadvance 140214043218-phpapp01
Abapdebuggingfrombasictoadvance 140214043218-phpapp01Abapdebuggingfrombasictoadvance 140214043218-phpapp01
Abapdebuggingfrombasictoadvance 140214043218-phpapp01IT TRAINER
 
Exception Handling in C++
Exception Handling in C++Exception Handling in C++
Exception Handling in C++Deepak Tathe
 

Ähnlich wie Dive into SObjectizer 5.5. Fourth part. Exception (20)

What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)
 
Static analysis and ROI
Static analysis and ROIStatic analysis and ROI
Static analysis and ROI
 
Static analysis and ROI
Static analysis and ROIStatic analysis and ROI
Static analysis and ROI
 
Exception Handling in UiPath.pptx
Exception Handling in UiPath.pptxException Handling in UiPath.pptx
Exception Handling in UiPath.pptx
 
IRJET- Technique of Finding the Defect in Software Testing
IRJET- Technique of Finding the Defect in Software TestingIRJET- Technique of Finding the Defect in Software Testing
IRJET- Technique of Finding the Defect in Software Testing
 
QA Best Practices
QA  Best PracticesQA  Best Practices
QA Best Practices
 
Introduction to Exception
Introduction to ExceptionIntroduction to Exception
Introduction to Exception
 
Certification preparation - Error Handling and Troubleshooting recap.pptx
Certification preparation - Error Handling and Troubleshooting recap.pptxCertification preparation - Error Handling and Troubleshooting recap.pptx
Certification preparation - Error Handling and Troubleshooting recap.pptx
 
$Cash
$Cash$Cash
$Cash
 
$Cash
$Cash$Cash
$Cash
 
Why test with flex unit
Why test with flex unitWhy test with flex unit
Why test with flex unit
 
Unit Testing in iOS
Unit Testing in iOSUnit Testing in iOS
Unit Testing in iOS
 
VBscript
VBscriptVBscript
VBscript
 
Basic Debugging
Basic DebuggingBasic Debugging
Basic Debugging
 
Abapdebuggingfrombasictoadvance 140214043218-phpapp01
Abapdebuggingfrombasictoadvance 140214043218-phpapp01Abapdebuggingfrombasictoadvance 140214043218-phpapp01
Abapdebuggingfrombasictoadvance 140214043218-phpapp01
 
Exception handling
Exception handlingException handling
Exception handling
 
How to handle exceptions in Java Technology
How to handle exceptions in Java Technology How to handle exceptions in Java Technology
How to handle exceptions in Java Technology
 
Uft Basics
Uft BasicsUft Basics
Uft Basics
 
Exception Handling in C++
Exception Handling in C++Exception Handling in C++
Exception Handling in C++
 

Mehr von Yauheni Akhotnikau

Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Yauheni Akhotnikau
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...Yauheni Akhotnikau
 
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Yauheni Akhotnikau
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Yauheni Akhotnikau
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Yauheni Akhotnikau
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My EyesYauheni Akhotnikau
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allYauheni Akhotnikau
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Yauheni Akhotnikau
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Yauheni Akhotnikau
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9Yauheni Akhotnikau
 
What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8Yauheni Akhotnikau
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьYauheni Akhotnikau
 

Mehr von Yauheni Akhotnikau (15)

Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
 
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9
 
What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная часть
 
Обзор SObjectizer 5.5
Обзор SObjectizer 5.5Обзор SObjectizer 5.5
Обзор SObjectizer 5.5
 

Dive into SObjectizer 5.5. Fourth part. Exception

  • 1. Dive into SObjectizer-5.5 SObjectizer Team, Jan 2016 Fourth Part: Exceptions (at v.5.5.15)
  • 2. This is the next part of the series of presentations with deep introduction into features of SObjectizer-5.5. This part is dedicated to usage of exceptions. In particular: ● why exceptions are used in SObjectizer Run-Time; ● what exceptions are used by SObjectizer-5; ● how SObjectizer-5.5 handles exceptions from agents; ● how a custom exception logger could be set; ● when and why SObjectizer can call std::abort(). SObjectizer Team, Jan 2016
  • 3. Why SObjectizer Run-Time Uses Exceptions SObjectizer Team, Jan 2016
  • 4. Exceptions are the primary way of error reporting in SObjectizer-5. There are no methods/functions which use return codes for indication of success or failure. Any method/function either finishes successfully or throws an exception. If a user does a valid call and here are all necessary resources (like RAM, OS threads and so on) then there is no source for a failure... SObjectizer Team, Jan 2016
  • 5. ...but if something goes wrong (like insufficient amount of RAM or inability to start yet another OS thread) then returning an error code as indication of failure is not a good idea. SObjectizer Team, Jan 2016
  • 6. Heavy usage of exceptions is a consequence of experience from several years with SObjectizer-4 in production. Error codes were used in SObjectizer-4. And the main lesson learned was: If an error handling could be forgotten then it will be forgotten. SObjectizer Team, Jan 2016
  • 7. The most unpleasant error in SObjectizer-4 was unsuccessful subscription. If a subscription failed but error is not handled then the work of an agent will be continued. But the agent will work incorrectly. And it could take a long time before the incorrectness will be found and fixed. SObjectizer Team, Jan 2016
  • 8. The main purpose of exceptions in SObjectizer-5 is to prevent the disregard of errors. Ignoring error code is easier than ignoring of an exception. Because of that all methods/functions like creating coops or subscribing of events throw exceptions in the case of error. SObjectizer Team, Jan 2016
  • 9. More than four years of working with SObjectizer-5 show that SObjectizer-related exceptions are not an issue. Just because they are thrown when a programmer does something wrong. It is hard to get SObjectizer-5 to throw an exception in normal situation... SObjectizer Team, Jan 2016
  • 10. For example, if agent creates a legal subscription for existing mbox there is no reason for exception… ...except the case of lack of memory. But in this particular case it is better to throw an exception instead of сontinuation of execution without subscription made or abortion of a whole application. That is why SObjectizer-5.5 uses exceptions instead of error codes. SObjectizer Team, Jan 2016
  • 11. If you do not like exceptions and prefer dealing with error code in plain-old-C-style... SObjectizer Team, Jan 2016
  • 12. If you do not like exceptions and prefer dealing with error code in plain-old-C-style... Then you probably is trying to use an inappropriate framework. It seems that SObjectizer-5 is a wrong choice for you. Just try to find something else. SObjectizer Team, Jan 2016
  • 13. What Exceptions Are Used By SObjectizer? SObjectizer Team, Jan 2016
  • 14. SObjectizer-5 doesn’t use a complex hierarchy of exception classes. There is only one class for representing SObjectizer-related exceptions: so_5::exception_t. It is derived from std::runtime_error. SObjectizer Team, Jan 2016
  • 15. Method exception_t::what(), inherited from std::exception, returns textual description of an error. But there is exception_t::error_code() method which returns internal error code represented as int. All SObjectizer error codes are defined inside so_5 namespace as constants with prefix rc_ in their names: rc_disp_start_failed, rc_parent_coop_not_found and so on. SObjectizer Team, Jan 2016
  • 16. So if it is necessary to catch, analyze and handle SObjectizer-related exception it could be done like that: try { ... // Some action with SObjectizer. } catch( const so_5::exception_t & x ) { if( so_5::rc_named_disp_not_found == x.error_code() ) ... // Create named dispatcher and try again. else throw; } SObjectizer Team, Jan 2016
  • 18. There is one simple rule: Normal agents should provide no-throw guarantee! SObjectizer Team, Jan 2016
  • 19. It means that an exception should not go out of an event- handler. It is because SObjectizer doesn’t know what to do with that exception. And doesn’t know the actual state of agent: is the agent in the correct state and could process next message or the agent’s internals are broken and no more messages must be delivered to the agent. SObjectizer Team, Jan 2016
  • 20. So the best way is to catch and handle all exception inside an agent’s event-handler. But what if an exception is going out anyway? SObjectizer Team, Jan 2016
  • 21. When SObjectizer detects an exception of type std::exception (or derived from it) the following actions are performed: ● the exception caught is logged by a special exception logger (more about it below); ● virtual method so_exception_reaction() is called for the agent who threw the exception; ● perform action(s) in dependence of so_exception_reaction() result. SObjectizer Team, Jan 2016
  • 22. Virtual method so_exception_reaction() can return one of the following values... SObjectizer Team, Jan 2016
  • 23. so_5::abort_on_exception This value means that the whole application must be terminated immediately by calling std::abort(). SObjectizer Team, Jan 2016
  • 24. so_5::shutdown_sobjectizer_on_exception This value means that: ● the agent who threw the exception will be switched to a special state (in that state it cannot handle other messages); ● SObjectizer Environment in which the exception has been caught will be shutdowned the usual way. This value useful if agent provides basic exception guarantee (no resources leaks) and application can be shutdowned normally. SObjectizer Team, Jan 2016
  • 25. so_5::deregister_coop_on_exception This value means that: ● the agent who threw the exception will be switched to a special state (in that state it cannot handle other messages); ● the coop which holds the problematic agent will be deregistered. This value useful if agent provides basic exception guarantee (no resources leaks) and application can continue its work after deregistration of that coop. For example, the coop will be automatically registered again by some supervisor. SObjectizer Team, Jan 2016
  • 26. so_5::ignore_exception This value means that no more actions should be performed by SObjectizer. This value is useful if agent provides strong exception guarantee. SObjectizer assumes that no damage has been made and work could be safely continued. SObjectizer Team, Jan 2016
  • 27. so_5::inherit_exception_reaction This value means that actual exception reaction needs to be received from agent’s coop. SObjectizer call exception_reaction() method for agent’s coop. One of the values described above could be received. The appropriate action will be performed. SObjectizer Team, Jan 2016
  • 28. But the value so_5::inherit_exception_reaction could be returned by coop_t::exception_reaction() method. In that case SObjectizer will call exception_reaction() method for the parent coop (if exists). And then for the parent of the parent and so on. If the top-most parent coop returns inherit_exception_reaction then exception_reaction() method will be called for SObjectizer Exception instance. That method usually returns abort_on_exception. SObjectizer Team, Jan 2016
  • 29. By default agent_t::so_exception_reaction() and coop_t:: exception_reaction() return inherit_exception_reaction value. By default environment_t::exception_reaction() return abort_on_exception. So the application will be aborted in the case of an uncaught exception by default. SObjectizer Team, Jan 2016
  • 30. A user can set appropriate exception reaction for the whole coop by coop_t::set_exception_reaction() method: env.introduce_coop( []( so_5::coop_t & coop ) { coop.set_exception_reaction( so_5::deregister_coop_on_exception ); ... } ); In that case an exception from any coop’s agent will lead to deregistration of the coop (but only if agent’s so_exception_reaction() returns inherit_exception_reaction value). SObjectizer Team, Jan 2016
  • 31. An exception reaction for the whole SObjectizer Environment can be set via Environment’s parameters: so_5::launch( []( so_5::environment_t & env ) { ... // Starting code. }, []( so_5::environment_params_t & params ) { ... // Environment parameters tuning code. // Setting the exception reaction for the whole Environment. params.exception_reaction( so_5::shutdown_sobjectizer_on_exception ); } ); SObjectizer Team, Jan 2016
  • 33. There is a possibility to know what the reason was behind the coop deregistration. When a coop is deregistered a special value must be passed to environment_t::deregister_coop(). This value is a “coop dereg reason”. There are several predefined values which are defined as constants in so_5::dereg_reason namespace... SObjectizer Team, Jan 2016
  • 34. ● normal. Coop’s deregistration is a part of application logic; ● shutdown. Deregistration is a part of Environment’s shutdown process; ● parent_deregistration. Coop is deregistered because its parent coop is deregistered. ● unhandled_exception. Coop is deregistered because of unhandled exception. There are several additional constants but they intended for use by a programmer, not SObjectizer. SObjectizer Team, Jan 2016
  • 35. Coop dereg reason is passed to coop dereg notificator. So a notificator can use this value for performing some actions. For example for restarting a cooperation in the case of exception... SObjectizer Team, Jan 2016
  • 36. Restart coop on exception example (1/3): #include <iostream> #include <so_5/all.hpp> void start_coop( so_5::environment_t & env ) { env.introduce_coop( [&]( so_5::coop_t & coop ) { struct raise_exception : public so_5::signal_t {}; // The single agent of the coop. // Will throw an exception after one second from registration. auto agent = coop.define_agent(); agent.on_start( [agent] { so_5::send_delayed< raise_exception >( agent, std::chrono::seconds(1) ); } ) .event< raise_exception >( agent, [] { throw std::runtime_error( "Just a test exception" ); } ); SObjectizer Team, Jan 2016
  • 37. Restart coop on exception example (2/3): // Tell SObjectizer to deregister the coop on exception. coop.set_exception_reaction( so_5::deregister_coop_on_exception ); // Add notificator which will initiate reregistration of the coop. coop.add_dereg_notificator( []( so_5::environment_t & env, const std::string & coop_name, const so_5::coop_dereg_reason_t & why ) { std::cout << "Deregistered: " << coop_name << ", reason: " << why.reason() << std::endl; if( so_5::dereg_reason::unhandled_exception == why.reason() ) start_coop( env ); } ); } ); } SObjectizer Team, Jan 2016
  • 38. Restart coop on exception example (3/3): int main() { so_5::launch( []( so_5::environment_t & env ) { // Register coop the first time. start_coop( env ); // Take some time to the example to work. std::this_thread::sleep_for( std::chrono::seconds( 5 ) ); env.stop(); } ); } SObjectizer Team, Jan 2016
  • 40. Every unhandled exception is logged. Default exception logger uses std::cerr as an output stream. A user can set its own custom exception logger. SObjectizer Team, Jan 2016
  • 41. An exception logger must be derived from class so_5::event_exception_logger_t. At least one method, log_exception(), must be overridden and implemented. It could looks like... SObjectizer Team, Jan 2016
  • 42. A very simple implementation of event_exception_logger_t: class spd_exception_logger : public so_5::event_exception_logger_t { public : spd_exception_logger() : logger_( spdlog::rotating_logger_mt( "file_logger", "logs/exceptions", 10*1024*1024 ) ) {} virtual void log_exception( const std::exception & ex, const std::string & coop_name ) override { logger_->alert( "Unhandled exception from coop '{}': {}", coop_name, ex.what() ); } private : std::shared_ptr< spdlog::logger > logger_; }; SObjectizer Team, Jan 2016
  • 43. There are two ways to set up a custom exception logger... SObjectizer Team, Jan 2016
  • 44. The first one is usage of Environment parameters: so_5::launch( []( so_5::environment_t & env ) { ... // Starting code. }, []( so_5::environment_params_t & params ) { ... // Environment parameters tuning code. // Setting the exception logger. params.event_exception_logger( so_5::event_exception_logger_unique_ptr_t{new spd_exception_logger{}} ); } ); SObjectizer Team, Jan 2016
  • 45. The second one is usage of Environment’s install_exception_logger() method: so_5::launch( []( so_5::environment_t & env ) { env.install_exception_logger( so_5::event_exception_logger_unique_ptr_t{ new spd_exception_logger{} } ); ... // Starting code. } ); The main difference between those approaches is the ability to change exception logger on working Environment via install_exception_logger() method. SObjectizer Team, Jan 2016
  • 46. When and why SObjectizer calls std::abort()? SObjectizer Team, Jan 2016
  • 47. There are some situations where SObjectizer cannot throw an exception and has to call abort() instead. SObjectizer Team, Jan 2016
  • 48. One of them is nested exceptions during handling an uncaught exception from some agent’s event handler. For example: ● SObjectizer calls log_exception() method for custom exception logger; ● log_exception() throws an exception; ● SObjectizer calls abort(). SObjectizer Team, Jan 2016
  • 49. Another one is related to delayed and periodic messages. If the timer thread can’t send a message instance then abort() will be called. It is because inability to send a delayed/periodic message is a violation of an important contract: if delayed/periodic message was successfully scheduled then it must be sent. There is no other way to report a violation of that contract except calling the abort() function. SObjectizer Team, Jan 2016
  • 50. There are some other situations when SObjectizer calls abort(). They are related to problems during recovery from some previous errors. There is a possibility of errors during registration of some coop. An attempt to create another working thread in a dispatcher can fail. SObjectizer will revert all changes which have been made before that failure. If some exception is thrown during this recovery SObjectizer has no choice except to call abort(). SObjectizer Team, Jan 2016
  • 51. So there are places in the SObjectizer code where abort() is called. But abort() is called by SObjectizer only in the case of a very serious problem. When there is no other way to continue correct work of an application. SObjectizer Team, Jan 2016
  • 52. Additional Information: Project’s home: http://sourceforge.net/projects/sobjectizer Documentation: http://sourceforge.net/p/sobjectizer/wiki/ Forum: http://sourceforge.net/p/sobjectizer/discussion/ Google-group: https://groups.google.com/forum/#!forum/sobjectizer GitHub mirror: https://github.com/masterspline/SObjectizer