A few problems with the FIX8 1.0 GA version

243 views
Skip to first unread message

Peter D

unread,
Feb 5, 2014, 5:36:45 PM2/5/14
to fix8-de...@googlegroups.com
I was using FIX8 v0.10.0. Everything works, then yesterday I was trying to switch to the new GA version, I found a few issues. The most serious issue is I can't get callbacks. If the new Lib is API breaking, please let me know what I need to change to be able to get the callbacks.

1. Even I set the login_retries="10" in my session setting config file, but it didn't reconnect when I receive an Logout.
2. Can't get any callbacks except Logon, Logout. 

When I gets a ExecutionReport, it will call handle_application.
bool MySessionClient::handle_application(const unsigned seqnum, const Message *&msg)
{
    return enforce(seqnum, msg) || msg->process(_router); 
}

In My_classes.hpp, then process() is called.
class ExecutionReport : public Message
{
bool process(Router& rt) const {  return (static_cast<My_Router&>(rt))(this); }
}

Then it should call, but never called. 

class MyRouterClient : public FIX8::ILink::My_Router { 
virtual bool operator() (const FIX8::ILink::ExecutionReport *msg) const
{ std::cerr << "Recv ExecutionReport:" << *msg << std::endl;} 
}

Dakka

unread,
Feb 5, 2014, 5:41:26 PM2/5/14
to fix8-de...@googlegroups.com
Check the FAQ. This issue is discussed there (section 4c). handle_application must be defined in a compilation unit (.cpp) and not in your header.
/dakka

Dakka

unread,
Feb 5, 2014, 6:03:12 PM2/5/14
to fix8-de...@googlegroups.com
You might also want to check that all of your f8c generated code has been completely regenerated.
We have tested the message processing idiom in 1.0.0 extensively and know it to work as expected.
/dakka

On Thursday, 6 February 2014 09:36:45 UTC+11, Peter D wrote:

Peter D

unread,
Feb 6, 2014, 12:51:28 AM2/6/14
to fix8-de...@googlegroups.com
I double check, In my session class, in header file, I only did declaration, the definition is in the cpp file.
virtual bool handle_application(const unsigned seqnum, const FIX8::Message *&msg);

And I can get into the handle_application, then ExecutionReport's process(), then fail on " static_cast<Generated_Router&>(rt))(this) " 

The static_cast looks suspicious to me. Since it convert to Generated_Router, and it doesn't know MyRouterClient. My coworkers was trying to use it yesterday on a separated project, and can't get it to work either. Hope you can help.

class MyRouterClient : public FIX8::MyNameSpace::Generated_Router

bool MySessionClient::handle_application(const unsigned seqnum, const Message *&msg) 
{
     return enforce(seqnum, msg) || msg->process(_router);
}

In My_classes.hpp
class ExecutionReport : public Message
{
    ...
    bool process(Router& rt) const {  return (static_cast< Generated_Router&>(rt))(this); } 

Dakka

unread,
Feb 6, 2014, 1:03:27 AM2/6/14
to fix8-de...@googlegroups.com
Hello,

your _router member in your session must be of the type MyRouterClient. The type that it appears is wrong. The process template method infers this type when called the actual router method. Check the examples and you will see that the session class you define holds a router object. This must the be your derived router class or if no overrides are required, the compiler generated router. Your derived router must derive from the compiler generated router.

/dakka

Peter D

unread,
Feb 7, 2014, 2:02:46 AM2/7/14
to fix8-de...@googlegroups.com
No, I did what you describe, the problem is more deep. 
MyRouterClient : public FIX8::MyNameSpace::Generated_Router  
class MySessionClient
{
    MyRouterClient _router;
}

I got down to the problem of polymorphism. The operator()(const ExecutionReport *msg) is never called, none of the Router class( Router, Generated_Router, MyRouterClient)'s operator()(const ExecutionReport *msg) is called (I put print out in all of them, but nothing got print out). 

I did another test, put a member variable and test() function in Generated_Router and MyRouterClient. Do static_cast to Generated_Router, then print out the value, and call the test() function. The value is correct, but the test() function is never called.
class ExecutionReport : public Message
{   ...
    bool process(Router& rt) const {  return (static_cast< Generated_Router&>(rt))(this); 
}
 
I kind of gave up for now, and rolled back to version 0.10.0. This could be a compiler related issue. My environment is Linux with C++ 11. Thanks.


Dakka

unread,
Feb 7, 2014, 2:08:23 AM2/7/14
to fix8-de...@googlegroups.com


On Friday, 7 February 2014 18:02:46 UTC+11, Peter D wrote:
No, I did what you describe, the problem is more deep. 
MyRouterClient : public FIX8::MyNameSpace::Generated_Router  
class MySessionClient
{
    MyRouterClient _router;
}

I got down to the problem of polymorphism. The operator()(const ExecutionReport *msg) is never called, none of the Router class( Router, Generated_Router, MyRouterClient)'s operator()(const ExecutionReport *msg) is called (I put print out in all of them, but nothing got print out). 

I did another test, put a member variable and test() function in Generated_Router and MyRouterClient. Do static_cast to Generated_Router, then print out the value, and call the test() function. The value is correct, but the test() function is never called.
class ExecutionReport : public Message
{   ...
    bool process(Router& rt) const {  return (static_cast< Generated_Router&>(rt))(this); 

What compiler are you using?
Why don't you attach your router class, session class and your generated code so we can see what is going on.


/dakka

Sergey Sedreev

unread,
Feb 7, 2014, 5:28:15 AM2/7/14
to fix8-de...@googlegroups.com
I've been using both dev & main branches and haven't seen the problem yet. Could you please give us a source code with usage sample just to reproduce the problem?
Serey

пятница, 7 февраля 2014 г., 11:08:23 UTC+4 пользователь Dakka написал:

Peter D

unread,
Feb 19, 2014, 5:37:43 PM2/19/14
to fix8-de...@googlegroups.com
Turns out I was using version 0.10.0, and when I do make&make install. It puts it on /usr/local/include/fix8. So when compile with GA version. Some code is compiled with the older version. Causing the problem. Sorry for the confusion.

But I still have issues with two things:
1. Doesn't try to reconnect by default. I complied the GA version code with 0.10.0 version. Seems we don't check the attempts in the GA version. I have to change the while true loop back to version 0.10.0's for loop, and change excepted to default to true to get it to work. Is there a particular reason for the while true loop?

In class ReliableClientSession : public ClientSession<T>
{
        int operator()()
              while(true)    // V 0.10.0    for (; ++_attempts <= this->_loginParameters._login_retries; )
              {
                     //bool excepted(false);
              }
         }
}

2. If I change my IP to something invalid, it cores. Say: "ip="10.106.109.13"" is working fine in the xml file. Change it to ip="10.106.109.131", it will core. 

Thanks
Peter

David Dight

unread,
Feb 19, 2014, 6:47:39 PM2/19/14
to fix8-de...@googlegroups.com
Hello Peter,
When you say GA version doesn't reconnect by default - has there been an unexpected disconnect or socket error in your application? If not then the reliable session will not attempt to reconnect. Looking at the code, I can see that the maximum reconnect attempts would not be honoured, however if any exception is raised, control will stay within the while loop.

With respect to the invalid IP, a net exception should be thrown. If you set an impossible IP, you should get an exception with "Host not found". You need to catch std::exception. If you are still getting a core dump, pls attach a stack trace.

/dakka


--
You received this message because you are subscribed to the Google Groups "fix8 developer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fix8-develope...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Peter D

unread,
Feb 20, 2014, 3:06:14 PM2/20/14
to fix8-de...@googlegroups.com, dav...@fix8.org
Crash when I use wrong IP.
#0  0x0000003b9d008143 in pthread_join () from /lib64/libpthread.so.0
#1  0x00007f84908b655b in FIX8::Connection::stop() ()
    at ../include/fix8/thread.hpp:127
#2  0x00007f84908a5da9 in FIX8::Session::stop() () at session.cpp:213
#3  0x0000000000423723 in FIX8::ReliableClientSession<CMESessionClient>::operator()() ()
    at /home/wdou/3p/fix8-1.0.0/include/fix8/sessionwrapper.hpp:405
#4  0x000000000041b861 in void* FIX8::_dthreadcore::_run<FIX8::dthread<FIX8::ReliableClientSession<CMESessionClient> >::_helper>(void*) ()
    at /home/wdou/3p/fix8-1.0.0/include/fix8/thread.hpp:206
#5  0x0000003b9d0079d1 in start_thread () from /lib64/libpthread.so.0
#6  0x0000003b9c8e8b6d in clone () from /lib64/libc.so.6


And for the other problem for reconnect. I see what you are saying. But the behavior is different than the version 0.10.0. Sometimes, when exchange doesn't like your sequence number. They will log you out. Then you are supposed to try relogin with the connect sequence number. With current setting, I can automatically reconnect when exchange disconnect me. Any suggestions? Or do you think my fix will be fine? :
In class ReliableClientSession : public ClientSession<T>
{
        int operator()()
              for (; ++_attempts <= this->_loginParameters._login_retries; )
              {
                     bool excepted(true);
              }
         }
}

Peter D

unread,
Feb 21, 2014, 1:33:05 PM2/21/14
to fix8-de...@googlegroups.com, dav...@fix8.org
The crash looks like to be caused by calling join on a uninitialized variable.

David Dight

unread,
Feb 21, 2014, 2:54:17 PM2/21/14
to fix8-de...@googlegroups.com

Have you changed the thread call to see is this resolves it?

David Dight

unread,
Feb 21, 2014, 3:27:15 PM2/21/14
to fix8-de...@googlegroups.com
I haven't observed this problem so if you can resolve it with something like this then we can fix it...

in fix8/thread.hpp change

int join() { return pthread_join(_tid, reinterpret_cast<void **>(&_exitval)) ? -1 : _exitval; }

to

int join()
{
void *rptr(&_exitval); 
return pthread_join(_tid, &rptr) ? -1 : _exitval; 
}

--

fix8

Modern open source FIX framework featuring complete schema customisation, high performance and fast development.

David L. Dight

Dakka

unread,
Feb 21, 2014, 3:46:06 PM2/21/14
to fix8-de...@googlegroups.com, dav...@fix8.org
Hello,

I was able to reproduce your reconnect issue with the ReliableClientSession. It appears that prior to 1.0.0, the reliable client would always reconnect, regardless of error. For resynchronisation errors this is required. For otherwise normal operation, this isn't. Since we can probably assume that a client exit would be system initiated and therefore not likely to elicit a reconnect sequence, we should restore the 0.10.0 behaviour.

Can you raise a ticket in Jira and we'll fix this in 1.0.2.

/dakka 

Peter D

unread,
Feb 27, 2014, 4:56:55 PM2/27/14
to fix8-de...@googlegroups.com, dav...@fix8.org

Gunjan Munjal

unread,
May 19, 2018, 8:09:47 AM5/19/18
to fix8 developer
I had a crash at this point

return getid() != get_threadid() ? pthread_join(_tid, nullptr) ? -1 : 0 : -1;

I can't remember which object's destruction or stop was calling this.
But the problem was _tid was 0 in that case, I added a check and then it worked fine.
Reply all
Reply to author
Forward
0 new messages