Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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