TimerTimeout() doesnt seem to work

Could anyone please enlighten me on why the TimerTimeout() fails to timeout and unblock the MsgSend(). I’ve checked that the client process is currently blocked in REPLY.

Would appreciate some pointers.

SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/neutrino.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <unistd.h>
#include <errno.h>

#define SEC_NSEC 1000000000LL

int main(int argc, char *argv[]) {

	pid_t pid;

	/*
	 * Using fork to run both server and client
	 */

	pid = fork();
	
	if (pid > 0) { 	/* Server code */
		printf("server: forked\n");
		
		/* Server variables */
		name_attach_t * attach;
		//struct _msg_info * rcv_info;
		int rcv_id;
		char rcv[30];
		int conn_id;
		
		/* Create channel */
		if ((attach = name_attach(NULL, "channel", 0)) == NULL) {
			printf("server: exit, failed to create channel\n");
			return EXIT_FAILURE;
		}
		
		printf("server: create and attached to chid %d\n", attach->chid);
		
		/* Attach to channel */
		if ((conn_id = ConnectAttach(0,0,attach->chid, _NTO_SIDE_CHANNEL, 0)) == -1) return EXIT_FAILURE;
	
		printf("server: conn_id=%d, start to loop\n", conn_id);

		
		int i = 0;
		while (1) {
			
			/* Recieve message */
			rcv_id = MsgReceive (attach->chid, rcv, sizeof(rcv), NULL);
			if (rcv_id == 0) {
				printf("server: recv seq=%d pulse\n", i);
			} else {
				printf("server: recv seq=%d id=%d datalen=%d data=[%s]\n",i, rcv_id, strlen(rcv), rcv);
				
			}
			++i;
		}
	
	} else if (pid == 0) { 	/* Client code */
		printf("client: forked\n");
		
		/* Client variables */
		int conn_id;
		char client_send[30];
		char client_reply[30];
		
		/* Connect to named channel */
		if ((conn_id = name_open("channel", 0)) == -1) return EXIT_FAILURE;
		
		printf("client: conn_id=%d, start sending msgs\n", conn_id);
			
		snprintf(client_send,sizeof(client_send), "%s", "TEST" );

		printf("client: send datalen=%d data=[%s]\n", strlen(client_send), client_send);

		struct sigevent event;
		SIGEV_UNBLOCK_INIT(&event);
		
		uint64_t timeout;
		timeout = SEC_NSEC;
	
		if (TimerTimeout(CLOCK_REALTIME, _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, &event, &timeout, NULL) == -1) {
			switch (errno){
				case EAGAIN:
					printf("client: no kernel timer entries\n");
					break;
				case EFAULT:
					printf("client: ntime or otime or notify access fault\n");
					break;
				case EINTR:
					printf("client: signal interrupt\n");
					break; 
				case EINVAL:
					printf("client: invalid timer id\n");
					break;
				default:
					printf("client: undefined error\n");
					break;
			}			
		}

		printf("client: timer set\n");
		int send_r;
		send_r = MsgSend(conn_id, client_send, strlen(client_send)+1, client_reply, sizeof(client_reply));
		
		if (send_r == 0) {
			printf("client: rply datalen=%d data=[%s]\n", strlen(client_reply), client_reply);
		} else {
			switch (errno){
				case EBADF:
					printf("client: connection id bad\n");
					break;
				case EFAULT:
					printf("client: buffer fault\n");
					break;
				case EINTR:
					printf("client: signal interrupt\n");
					break; 
				case ESRCH:
					printf("client: server died\n");
					break;
				case ESRVRFAULT:
					printf("client: server fault\n");
					break;
				case ETIMEDOUT:
					printf("client: timed out\n");
					break;
				default:
					printf("client: undefined error\n");
					break;
			}
		}
		printf("client: exit\n");
		return EXIT_SUCCESS;
		
		
	} else { /* fork() failed */
		return EXIT_FAILURE;
	}
	
	
}

CONSOLE OUTPUT

server: forked
client: forked
server: create and attached to chid 1
server: conn_id=1073741827, start to loop
client: conn_id=1073741825, start sending msgs
client: send datalen=4 data=[TEST]
client: timer set
server: recv seq=0 id=5 datalen=4 data=[TEST]

I haven’t looked closely at your code, so there may be a bug, but you might also want to look at what you are sending to. A resource manager can request that it be informed when a client is trying to unblock, say for example when it gets hit with a signal. This gives the resource manager the option to do some processing before allowing the client to go on. The down side to this is that the resource manager can ignore the request, which prevents the client from unblocking.

If I change the ntime parameter of TimerTimeout() to a NULL pointer, the MsgSend() unblocks immediately with a ETIMEDOUT errno, which is as documented. However the moment I specify a specific ntime value, the timeoutfails to work.

TimerTimeout(CLOCK_REALTIME, _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, &event, &timeout, NULL)
TimerTimeout(CLOCK_REALTIME, _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, &event, NULL, NULL)

Your code has a bug. You call printf between TimerTimeout and the MsgSend…

I guess it might need to be explained that printf calls MsgSend, so the TimerTimeout() is resolved by the time the 2nd MsgSend().