client: exception propagation from callbacks

Swallowing exceptions here hides some of our errors.
Particularly unrecoverable introspectionRegistry misses.
Instead, propagate up to Thread and close connection.
This commit is contained in:
Michael Davidsaver
2018-06-22 12:47:08 -07:00
parent 1670ff8f7c
commit d424202323
2 changed files with 38 additions and 47 deletions

View File

@@ -67,13 +67,9 @@ class ChannelGetFieldRequestImpl;
typedef std::map<pvAccessID, ResponseRequest::weak_pointer> IOIDResponseRequestMap;
#define EXCEPTION_GUARD(code) try { code; } \
catch (std::exception &e) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \
catch (...) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); }
#define EXCEPTION_GUARD(code) do { code; } while(0)
#define EXCEPTION_GUARD3(WEAK, PTR, code) {requester_type::shared_pointer PTR((WEAK).lock()); if(PTR) try { code; } \
catch (std::exception &e) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \
catch (...) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); }}
#define EXCEPTION_GUARD3(WEAK, PTR, code) do{requester_type::shared_pointer PTR((WEAK).lock()); if(PTR) { code; }}while(0)
#define SEND_MESSAGE(WEAK, PTR, MSG, MTYPE) \
do{requester_type::shared_pointer PTR((WEAK).lock()); if(PTR) (PTR)->message(MSG, MTYPE); }while(0)
@@ -273,41 +269,32 @@ public:
Status status;
status.deserialize(payloadBuffer, transport.get());
try
if (qos & QOS_INIT)
{
if (qos & QOS_INIT)
if (status.isSuccess())
{
if (status.isSuccess())
{
// once created set destroy flag
Lock G(m_mutex);
m_initialized = true;
}
initResponse(transport, version, payloadBuffer, qos, status);
// once created set destroy flag
Lock G(m_mutex);
m_initialized = true;
}
else
initResponse(transport, version, payloadBuffer, qos, status);
}
else
{
bool destroyReq = false;
if (qos & QOS_DESTROY)
{
bool destroyReq = false;
if (qos & QOS_DESTROY)
{
Lock G(m_mutex);
m_initialized = false;
destroyReq = true;
}
normalResponse(transport, version, payloadBuffer, qos, status);
if (destroyReq)
destroy();
Lock G(m_mutex);
m_initialized = false;
destroyReq = true;
}
}
catch (std::exception &e) {
LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what());
}
catch (...) {
LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__);
normalResponse(transport, version, payloadBuffer, qos, status);
if (destroyReq)
destroy();
}
}
@@ -2508,11 +2495,13 @@ public:
transport->ensureData(4);
// TODO check and optimize?
ResponseRequest::shared_pointer rr = _context.lock()->getResponseRequest(payloadBuffer->getInt());
if (rr.get())
if (rr)
{
ResponseRequest::shared_pointer nrr = dynamic_pointer_cast<ResponseRequest>(rr);
if (nrr.get())
nrr->response(transport, version, payloadBuffer);
rr->response(transport, version, payloadBuffer);
} else {
// oh no, we can't complete parsing this message!
// This might contain updates to our introspectionRegistry, which will lead to failures later on.
// TODO: seperate message parsing from user Operation lifetime...
}
}
};
@@ -2546,13 +2535,9 @@ public:
return;
ResponseRequest::shared_pointer rr = context->getResponseRequest(ioid);
if (rr.get())
if (rr)
{
ResponseRequest::shared_pointer nrr = dynamic_pointer_cast<ResponseRequest>(rr);
if (nrr.get())
nrr->response(transport, version, payloadBuffer);
else
return; // we cannot deserialize, we are lost in stream, we must stop
rr->response(transport, version, payloadBuffer);
}
else
return; // we cannot deserialize, we are lost in stream, we must stop
@@ -3821,7 +3806,7 @@ public:
if(!R) continue;
ChannelBaseRequester::shared_pointer req(R->getRequester());
if(!req) continue;
EXCEPTION_GUARD(req->channelDisconnect(connectionState==Channel::DESTROYED);)
EXCEPTION_GUARD(req->channelDisconnect(connectionState==Channel::DESTROYED););
}
}
}