Skip to content

EMA C++: poor handling of exception in application callback #337

@miczuc

Description

@miczuc

Hello.

If an exception is thrown in an application callback in a consumer, the EMA library does not behave well:
a) the dispatch thread stops
b) you only get poor log information
c) destructor of class Thread reports "Assertion `_threadId == 0' failed."
d) obviously the mutex "_userLock" in class OmmBaseImpl is left in the locked state

To test this, I changed your example Consumer/100_Series/100_MP_Streaming/Comsumer.cpp .
The version I used was 2.3.0 .

void AppClient::onUpdateMsg( const UpdateMsg& updateMsg, const OmmConsumerEvent& ) 
{
	cout << updateMsg << endl;		// defaults to updateMsg.toString()
	cout << "throwing std::invalid_argument for test in onUpdateMsg()" << endl;
	throw invalid_argument("TEST EXCEPTION");
}

This is the output of the program:

throwing std::invalid_argument for test in onUpdateMsg()
loggerMsg
TimeStamp: 11:42:23.559
ClientName: Consumer_1_1
Severity: Error
Text: EMA Exception Handler

Application: EMA Application
Process Id: 0x38166X

File: /local/jenkins/workspace/RTSDK_Core_DX1/OS/RH8-64/rcdev/source/rtsdk/Cpp-C/Ema/Src/Access/Impl/Thread.cpp
Line: 74
Exception occured
loggerMsgEnd

cons100-2.3.0.x: /local/jenkins/workspace/RTSDK_Core_DX1/OS/RH8-64/rcdev/source/rtsdk/Cpp-C/Ema/Src/Access/Impl/Thread.cpp:39: virtual refinitiv::ema::access::Thread::~Thread(): Assertion `_threadId == 0' failed.

So all you get as information is that there was an exception of some type somewhere somehow, not very helpful.
And what is the assertion in Thread::~Thread() good for? In my opinion that is complete senseless.
If you change the main function as shown below, you will see, that the call consumer.unregister()
hangs forever, blocked in:
refinitiv::ema::access::Mutex::lock (this=...) at /local/jenkins/workspace/RTSDK_Core_DX1/OS/RH8-64/rcdev/source/rtsdk/Cpp-C/Ema/Src/Access/Impl/Mutex.cpp:53

int main( int argc, char* argv[] )
{
        try {
                AppClient client;
                OmmConsumer consumer( OmmConsumerConfig().host( "localhost:14002" ).username( "user" ) );
                UInt64 h = consumer.registerClient( ReqMsg().serviceName( "DIRECT_FEED" ).name( "IBM.N" ), client );
                sleep( 5000 );                         // API calls onRefreshMsg(), onUpdateMsg(), or onStatusMsg()
                if(h) consumer.unregister(h); // blocks forever, if exception is thrown in callback
        } catch ( const OmmException& excp ) {
                cout << excp << endl;
        }
        return 0;
}

Hope, you will improve this ... Regards, Michael

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions