summaryrefslogtreecommitdiff
path: root/lib/server
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2014-10-31 22:09:42 +0000
committerChris Wilson <chris+github@qwirx.com>2014-10-31 22:09:42 +0000
commite8efeb785c158581be729aa1dee122f50789ac86 (patch)
treedd1fda26285a9255411c607b6910b79a89877242 /lib/server
parent9236e14007c068d7d9294d90aeb976eb9cecab84 (diff)
Refactor handling of exceptions in protocol server command executors.
Add a standard method to Replyable that will be called if a recoverable exception (a BoxException) occurs, and can return a protocol Message to be sent to the client, such as an error code for various standard errors, or rethrow the exception. If you want something different, catch exceptions and return the desired reply yourself, or you'll get the default handling.
Diffstat (limited to 'lib/server')
-rwxr-xr-xlib/server/makeprotocol.pl.in51
1 files changed, 36 insertions, 15 deletions
diff --git a/lib/server/makeprotocol.pl.in b/lib/server/makeprotocol.pl.in
index 65d1f3a9..d61a14d0 100755
--- a/lib/server/makeprotocol.pl.in
+++ b/lib/server/makeprotocol.pl.in
@@ -604,10 +604,11 @@ public:
virtual int GetTimeout() = 0;
void SendStreamAfterCommand(std::auto_ptr<IOStream> apStream);
-
+
protected:
std::list<IOStream*> mStreamsToSend;
void DeleteStreamsToSend();
+ virtual std::auto_ptr<$message_base_class> HandleException(BoxException& e) const;
private:
$replyable_base_class(const $replyable_base_class &rToCopy); /* do not call */
@@ -1077,24 +1078,31 @@ void $server_or_client_class\::DoServer($context_class &rContext)
// Run the command
try
{
- if(pobj->HasStreamWithCommand())
+ try
{
- std::auto_ptr<IOStream> apDataStream = ReceiveStream();
- SelfFlushingStream autoflush(*apDataStream);
- preply = pobj->DoCommand(*this, rContext, *apDataStream);
+ if(pobj->HasStreamWithCommand())
+ {
+ std::auto_ptr<IOStream> apDataStream = ReceiveStream();
+ SelfFlushingStream autoflush(*apDataStream);
+ preply = pobj->DoCommand(*this, rContext, *apDataStream);
+ }
+ else
+ {
+ preply = pobj->DoCommand(*this, rContext);
+ }
}
- else
+ catch(BoxException &e)
{
- preply = pobj->DoCommand(*this, rContext);
+ // First try a the built-in exception handler
+ preply = HandleException(e);
}
}
- catch (std::exception &e)
- {
- Send($cmd_classes{$error_message}());
- throw;
- }
catch (...)
{
+ // Fallback in case the exception isn't a BoxException
+ // or the exception handler fails as well. This path
+ // throws the exception upwards, killing the process
+ // that handles the current client.
Send($cmd_classes{$error_message}());
throw;
}
@@ -1183,19 +1191,32 @@ __E
}
elsif($writing_local)
{
+ print CPP <<__E;
+ std::auto_ptr<$message_base_class> apReply;
+ try
+ {
+__E
if($has_stream)
{
print CPP <<__E;
- std::auto_ptr<$message_base_class> apReply = rQuery.DoCommand(*this,
- mrContext, *apDataStream);
+ apReply = rQuery.DoCommand(*this, mrContext, *apDataStream);
__E
}
else
{
print CPP <<__E;
- std::auto_ptr<$message_base_class> apReply = rQuery.DoCommand(*this, mrContext);
+ apReply = rQuery.DoCommand(*this, mrContext);
__E
}
+
+ print CPP <<__E;
+ }
+ catch(BoxException &e)
+ {
+ // First try a the built-in exception handler
+ apReply = HandleException(e);
+ }
+__E
}
# Common to both client and local