TimerTimeout doesn't work

Hi,

I’m writing a classes-wrappers around MsgSend/MsgReceive (QNX 6.3.2). First version is done. I’ve planned to set timeouts for client MsgSend calls by TimerTimeout:

int CClient::Write( const void* sendBuf, size_t bufSz )
{
	int res;
	struct _io_write whdr;
	iov_t iov[2];
	
	SETIOV( iov+0, &whdr, sizeof(whdr) );
	SETIOV( iov+1, sendBuf, bufSz );
	
	whdr.type = _IO_WRITE;
	whdr.nbytes = bufSz;

            
    //timeout set (if server is down we will get ETIMEDOUT error)
    uint64_t timeout = 1*1000000000; 
    TimerTimeout( CLOCK_REALTIME, _NTO_TIMEOUT_SEND  |                _NTO_TIMEOUT_REPLY,  NULL, &timeout, NULL  );
     // 
	
            res = MsgSendv_r( m_serverId, iov, 2, iov, 1 );
	if( res < 0 )
		res = -res;
	return res;
}

At the server side there is an endless cycle with MsgReceive. I simulate server crash by sleep function. If i want to make client SEND blocked i place sleep(20) before MsgReceive. If i want the clinet be REPLY blocked, i place sleep(20) before MsgReply (after MsgReceive).

...
//sleep(20);
rcvid = MsgReceive( pServer->m_nameAttach->chid, &header, sizeof(header), &msg_info );
....
switch( header.type )
{
    case _IO_WRITE:
        //sleep(20);
        pServer->OnWrite( rcvid, header.io_write.xtype,                      header.io_write.nbytes );
        MsgReply( rcvid, EOK, NULL, 0 );
        break;		

The problem is timeout doesn’t work in case of REPLY blocked client (when i uncomment sleep before MsgReply).

Documentation says:

But i don’t set _NTO_CHF_UNBLOCK for the channel ( i do name_attach , that doesn’t set any flag for channel ). So, my client should be unblocked on timeout.

Is there any method to set timeout for MsgSend?

Thanks

Hello Alex2005 ,
Please try alarm or ualarm.
Regards,
Yuriy

Thanks for reply.

Alram() should work (I’ll try it), but I can’t understand what should I do in alarm handler.

For instance, user of my wrapper class does smth:

CClient c;
c.connect( server_name );
c.write( command );
c.disconnect();

So, if server become down at c.write() it would be nice to throw an exception or return an error.
In that case user of my class could try reconnect.
I can’t figure out how can i get such functionality with alarm() inside class code.

Setup a dummy signal handler which does nothing. Then MsgSend should return and set errno to EINTR. I am not sure why the timeout doesn’t work but I’d keep working at it. Signals requires extra care, mainly if you mix them with threads.

Mario, thanks for reply.

I’m going to solve the problem according to your suggesstion.

At the present the bug (or my error?) with TimerTimeout is the hardest bug in QNX for me.
I just want simple and straightforward method for unblocking MsgSend ( like TimerTimeout )

Thanks again.

I’ve tried alarm. sleep(20) function before MsgReply on server side was uncommented (client stays Reply blocked for 20 seconds).

i do a configuration in a main()

void handler( int sig, siginfo_t* siginfo, void* smth ){return;}
 
int main()
{
//tmp

	sigemptyset(&QNXClassesNS::sig);
	sigaddset(&QNXClassesNS::sig, SIGALRM );
	sigprocmask( SIG_BLOCK, &QNXClassesNS::sig, NULL );
	struct sigaction act;
	act.sa_mask = QNXClassesNS::sig;
	act.sa_sigaction = handler;
	act.sa_flags = SA_SIGINFO;
	if( sigaction( SIGALRM, &act, NULL ) < 0 )
		return EXIT_FAILURE;
	//tmp

and then set mask in a client thread

int CClient::Write(....)
{
....
SignalProcmask( 0,0, SIG_UNBLOCK, &sig, NULL );
alarm(1);
res = MsgSendv_r( m_serverId, iov, 2, iov, 1 );
alarm(0);

Signal handler is called ( in the client thread context ) just after 20 secondes.
So it seems to me that “alarm” doesn’t unblock MsgSend either.

What’s wrong with REPLY blocking?
How do you solve a problem of MsgSend blocking/unblocking?

Thank you.

Alex,

In your TimerTimeout call you have the 3rd parameter set to NULL. In the sample shown in the doc’s, they have an &event there and on the line above they do an event.sigev_notify = SIGEV_UNBLOCK;

I wonder if this is your problem? Of course this is going to generate a signal which means you need a dummy signal handler as Mario mentioned.

Tim

Tim, the doc says if you pass null for event, SIGEV_UNBLOCK is assumed.

Mario,

Yup, I read that too.

Of course the sample code that was given explictly set the event structure.

That made me wonder if part of the doc’s might be wrong. Since it only takes a couple of lines of code to test that theory I thought it might be worth doing since what Alex is doing should work.

Actually I just re-read Alex’s initial post. He does a name_attach() call. If you look at name_attach() in the doc’s you clearly see it definitely does set the _NTO_CHF_UNBLOCK flag on the channel. So there is no way his example is going to work because the sleep(20) isn’t going to let his server side ever get the pulse in the MsgReceive so he can unblock the other side (see the sample code in name_attach where it shows handling the request to unblock).

Tim

I tried a version with “event.sigev_notify = SIGEV_UNBLOCK;” It didn’t work too.

As for the _NTO_CHF_UNBLOCK flag, I can’t find in name_attach description (QNX 6.3.2 docs) anything about _NTO_CHF_UNBLOCK flag.
Could you give me a reference.

At the beginning I was afraid of channel flags that name_attach() could set internally but I found this text in name_attach() description:

Hi,
I’ve made a temp version of program without name_attach/name_open but with channelcreate(0)/connectattach to check Tim’s hint about channel flag. It works!
So, my problem is that name_attach() does set _NTO_CHF_UNBLOCK flag
(i can’t find this in documentation).

Now it’s not clear how to set/unset channel flags when i use name_attach()

Thanks.

Is it correct way to get a channel with name with unset flags (see code below)?

m_nameAttach = name_attach(...);
ChannelDestroy( m_nameAttach->chid );       
m_nameAttach->chid = ChannelCreate( 0 );

It works but looks like a “trick”.

Alex,

I think your trick is fine. If I remember correctly, name_attach() is a legacy call left over from QNX 4 for people who port code bases. The correct way to do things under QNX 6 is via a resource manager.

So the flag was probably being set to satisfy some QNX 4 functionality (it’s been forever since I did QNX 4 programming so I can’t say for sure) that you won’t be using/needing.

Tim

name_atttach provides transparent network name resolution something a resource manager on its own can’t do. Hence I don’t beleive name_attach is a legacy call.

Mario,

Aren’t you supposed to use Qnet to connect across a network if you want transparency? I’ve never done it but Robert Krten’s book Getting Started with QNX Neutrino 2 indicates that’s the way to go over using name_attach.

His book is also the place that calls out name_attach() as legacy QNX 4 calls and to be avoided in favor of resource managers/Qnet.

Of course his book (and his QNX Cookbook book) is a few years old now but both are still valuable resources that I use quite often for ideas when I’m looking at new designs.

Tim

P.S. Despite my reply above, I still use name_attach() when I don’t want to write a full resource manager.

As I know name_attach->msgsend more efficient that using resource manager, becouse: your call “write” copy data to res manager process space, so one copy data on write and one copy data on read → 2 copy more than using receive/send - somthing like that.

That’s not the case, as far as I know there is no extra copy however the resmgr frame work does extra work like parsing of the message, locking of the attribute etc.

Mario is correct. There is almost no penalty involved in resmgr vs. raw messaging.