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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions