Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - select() vs ionotify(): (8 Items)
   
select() vs ionotify()  
I've got one resource manager that gathers data and supports ionotify so clients can wait on data to arrive and then 
grab it.  I'd like to have another resource manager consume these data and process them further.  For this it seems that
 I should use ionotify() over select(), as ionotify can deliver pulses to my second resource manager.  This all makes 
sense, but while the following example using select() works, the ionotify() version doesn't receive messages.  I'm sure 
I'm doing something silly, but if someone could point me in the right direction for using ionotify(), I'd greatly 
appreciate it!

/////// select version: works
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/select.h>

int main( void )
{
  int fd;
  char buf[128];
  fd_set rfd;
  
  fd = open("/dev/pioint", O_RDONLY);
  if (fd < 0) {
    perror("open");
    return 1;
  }

  /*
   * Clear the set of read file descriptors, and * add the two we just got from the open calls. 
   */
  FD_ZERO( &rfd );
  FD_SET( fd, &rfd );

  for (;;) {
    select( 1+fd, &rfd, 0, 0, NULL);
    if( FD_ISSET( fd, &rfd ) ) {
      read(fd, buf, sizeof(buf));
      printf(buf);
    }
  }
  return 0;
}

/////// ionotify version: doesn't receive any even message

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/iomsg.h>
#include <sys/neutrino.h>

int main()
{
  int chid, coid;
  struct sigevent event;
  char buf[128];
  char msg[32];
  int r, rcvid;

  int fd = open("/dev/pioint", O_RDONLY);
  if (fd < 0) {
    perror("open");
    return 1;
  }
  chid = ChannelCreate(0);
  coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0);
  SIGEV_PULSE_INIT(&event, coid, 0,  SI_NOTIFY, 0);

  for (;;) {
    r = ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event);
    rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
    if (!rcvid) {
      read(r, &buf, 128);
      printf(buf);
    }
  }
  
  return 0;
}
Re: select() vs ionotify()  
Check the return value of notify.  If the condition is true, it doesn't arm the event, it instead returns the bits that 
were true.

David
From: community-noreply@qnx.com
Sent: August 28, 2020 11:33 PM
To: ostech-core_os@community.qnx.com
Reply-to: ostech-core_os@community.qnx.com
Subject: select() vs ionotify()


I've got one resource manager that gathers data and supports ionotify so clients can wait on data to arrive and then 
grab it.  I'd like to have another resource manager consume these data and process them further.  For this it seems that
 I should use ionotify() over select(), as ionotify can deliver pulses to my second resource manager.  This all makes 
sense, but while the following example using select() works, the ionotify() version doesn't receive messages.  I'm sure 
I'm doing something silly, but if someone could point me in the right direction for using ionotify(), I'd greatly 
appreciate it!

/////// select version: works
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/select.h>

int main( void )
{
  int fd;
  char buf[128];
  fd_set rfd;

  fd = open("/dev/pioint", O_RDONLY);
  if (fd < 0) {
    perror("open");
    return 1;
  }

  /*
   * Clear the set of read file descriptors, and * add the two we just got from the open calls.
   */
  FD_ZERO( &rfd );
  FD_SET( fd, &rfd );

  for (;;) {
    select( 1+fd, &rfd, 0, 0, NULL);
    if( FD_ISSET( fd, &rfd ) ) {
      read(fd, buf, sizeof(buf));
      printf(buf);
    }
  }
  return 0;
}

/////// ionotify version: doesn't receive any even message

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/iomsg.h>
#include <sys/neutrino.h>

int main()
{
  int chid, coid;
  struct sigevent event;
  char buf[128];
  char msg[32];
  int r, rcvid;

  int fd = open("/dev/pioint", O_RDONLY);
  if (fd < 0) {
    perror("open");
    return 1;
  }
  chid = ChannelCreate(0);
  coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0);
  SIGEV_PULSE_INIT(&event, coid, 0,  SI_NOTIFY, 0);

  for (;;) {
    r = ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event);
    rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
    if (!rcvid) {
      read(r, &buf, 128);
      printf(buf);
    }
  }

  return 0;
}




_______________________________________________

OSTech
http://community.qnx.com/sf/go/post120909
To cancel your subscription to this discussion, please e-mail ostech-core_os-unsubscribe@community.qnx.com
Attachment: HTML sf-attachment-mime39345 5.42 KB
Re: select() vs ionotify()  
I wondered about that. In my case it returns 0. As I’ve written the resource manager, too, the trouble could be there..
 But what I can’t quite understand is why select() works as I’d expect but ionotify() does not. 
Re: select() vs ionotify()  
Which version of QNX?
If you are using the newly-released 7.1 then you have to register the event (see MsgRegisterEvent()).

--Elad
Re: select() vs ionotify()  
Yes, this is 7.1 and from the MsgRegisterEvent documentation I see that I must register the event for it to delivered by
 default.  Thank you for pointing me in that direction!

But event after I make the additional kernel call to register:

  chid = ChannelCreate(0);
  coid = ConnectAttach(0, getppid(), chid, _NTO_SIDE_CHANNEL, 0);
  SIGEV_PULSE_INIT( &event, coid, SIGEV_PULSE_PRIO_INHERIT, SI_NOTIFY, 0 );
  SIGEV_MAKE_UPDATEABLE(&event);
  
  r = MsgRegisterEvent(&event, coid);
  if (r < 0) {
    perror("MsgRegisterEvent");
    return 1;
  }
 
my call:

r = ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event);

(which returns 0)
followed by:

rcvid = MsgReceivePulse( chid, &pulse, sizeof( pulse ), NULL );

doesn't receive the pulse?

Does select() do something else to enable the ionotify() to work that I'm missing?
Re: select() vs ionotify()  
Your call to MsgRegisterEvent() is incorrect. This is a tricky point when using pulse events, and you are not the first 
one to have got it wrong.
When you initialize the pulse event you give it the connection ID on which to deliver the pulse, in your case 'coid'. 
However, the connection ID argument to MsgRegisterEvent() is used to identify the server that is permitted to deliver 
the event (to prevent malicious servers from delivering unauthorized events). You passed 'coid', but that one is not 
connected to the server. In your case you should pass 'fd'.

--Elad
Re: select() vs ionotify()  
Thank you so much!  Indeed it works now!

And just to close the loop on this thread, I'd like to drop this "ionotification" into a second resource manager, which 
will provide "cooked" outputs to other clients, having processed data from the original resource manager.  Does the 
following seem like a reasonable way to connect the event into the resource manager / dispatch framework?  I think it 
should make a callback to a function called process_data() when the pulse arrives (passing a pointer to my own data in &
client_info)?

  struct sigevent event;

  /* Initialize an event structure, and attach a pulse to it */
  event.sigev_code = pulse_attach(dpp, MSG_FLAG_ALLOC_PULSE, 0,
				  &process_data, &client_info);
  if(event.sigev_code == -1) {
    fprintf(stderr, "Unable to attach notify pulse.\n");
    return EXIT_FAILURE;
  }
  /* Connect to our channel */
  event.sigev_coid = message_connect(dpp, MSG_FLAG_SIDE_CHANNEL);
  if(event.sigev_coid == -1) {
    fprintf(stderr, "Unable to attach to channel.\n");
    return EXIT_FAILURE;
  }
  
  event.sigev_notify = SIGEV_PULSE;
  event.sigev_priority = -1;

  MsgRegisterEvent(&event, fd);
  ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event);
Re: select() vs ionotify()  
I'll find a place to mention this in the docs.

> Your call to MsgRegisterEvent() is incorrect. This is a tricky point when 
> using pulse events, and you are not the first one to have got it wrong.
> When you initialize the pulse event you give it the connection ID on which to 
> deliver the pulse, in your case 'coid'. However, the connection ID argument to
>  MsgRegisterEvent() is used to identify the server that is permitted to 
> deliver the event (to prevent malicious servers from delivering unauthorized 
> events). You passed 'coid', but that one is not connected to the server. In 
> your case you should pass 'fd'.
> 
> --Elad