Cannot select() on a coid

I’m trying to write a program that select()s on both a connection id
and a socket. My observation is that if you include a coid in the
fd_set to select() then select() fails to return under any non-error
circumstances, even if there is activity on the socket. From what I
gather, a coid is a file descriptor, and therefore should be able to
participate in a select. This appears to be a bug.

Here is an example program that attempts to select on both stdin (not
in raw mode, but the point is valid), and a connection id. If you
select on both, then select never returns. If you select only on
stdin, then select returns on the first keystroke, correctly. This is
the same behaviour I see when selection on both a coid and a socket.

/* --------------------------------------------------------- /
/
Compile with cc -o sel sel.c */

/*

  • Attempts to select from both stdin and a connection id. Run
  • without arguments to only select on stdin. Run with any argument
  • to select on both. I know that stdin should be raw, but this proves
  • the point anyway.
  • If selecting on the connection id, input on stdin is not noticed.
  • This looks like a bug to me.
  • Also, cannot select on a coid that is _NTO_SIDE_CHANNEL
    */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>

int main (int argc, char** argv)
{
int kfd;
int chid, coid, rcvid;
fd_set fdset;
int nfds, maxfd;
char msg[1024];

kfd = fileno (stdin);

chid = ChannelCreate (0);
coid = ConnectAttach (ND_LOCAL_NODE, 0, chid, 0, 0);

for (;:wink:
{
FD_ZERO (&fdset);
FD_SET (kfd, &fdset);
if (argc > 1)
FD_SET (coid, &fdset);

maxfd = coid;
nfds = select (maxfd + 1, &fdset, NULL, NULL, NULL);
if (nfds > 0)
{
if (FD_ISSET (kfd, &fdset))
{
printf (“Keyboard input\n”);
exit (0);
}
if (FD_ISSET (coid, &fdset))
{
printf (“Input on coid\n”);
rcvid = MsgReceive (coid, msg, sizeof(msg), NULL);
MsgReply (rcvid, 0, msg, sizeof(msg));
}
}
else if (nfds == -1)
{
printf (“select error: %s\n”, strerror(errno));
exit (-1);
}
}
return (0);
}

/* --------------------------------------------------------- */


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

-seanb

Andrew Thomas <andrew@cogent.ca> wrote:

: I’m trying to write a program that select()s on both a connection id
: and a socket. My observation is that if you include a coid in the
: fd_set to select() then select() fails to return under any non-error
: circumstances, even if there is activity on the socket. From what I
: gather, a coid is a file descriptor, and therefore should be able to
: participate in a select. This appears to be a bug.

: Here is an example program that attempts to select on both stdin (not
: in raw mode, but the point is valid), and a connection id. If you
: select on both, then select never returns. If you select only on
: stdin, then select returns on the first keystroke, correctly. This is
: the same behaviour I see when selection on both a coid and a socket.

: /* --------------------------------------------------------- /
: /
Compile with cc -o sel sel.c */

: /*
: * Attempts to select from both stdin and a connection id. Run
: * without arguments to only select on stdin. Run with any argument
: * to select on both. I know that stdin should be raw, but this proves
: * the point anyway.
: *
: * If selecting on the connection id, input on stdin is not noticed.
: * This looks like a bug to me.
: *
: * Also, cannot select on a coid that is _NTO_SIDE_CHANNEL
: */

: #include <stdio.h>
: #include <string.h>
: #include <errno.h>
: #include <sys/select.h>
: #include <sys/netmgr.h>
: #include <sys/neutrino.h>

: int main (int argc, char** argv)
: {
: int kfd;
: int chid, coid, rcvid;
: fd_set fdset;
: int nfds, maxfd;
: char msg[1024];
:
: kfd = fileno (stdin);

: chid = ChannelCreate (0);
: coid = ConnectAttach (ND_LOCAL_NODE, 0, chid, 0, 0);

: for (;:wink:
: {
: FD_ZERO (&fdset);
: FD_SET (kfd, &fdset);
: if (argc > 1)
: FD_SET (coid, &fdset);

: maxfd = coid;
: nfds = select (maxfd + 1, &fdset, NULL, NULL, NULL);
: if (nfds > 0)
: {
: if (FD_ISSET (kfd, &fdset))
: {
: printf (“Keyboard input\n”);
: exit (0);
: }
: if (FD_ISSET (coid, &fdset))
: {
: printf (“Input on coid\n”);
: rcvid = MsgReceive (coid, msg, sizeof(msg), NULL);
: MsgReply (rcvid, 0, msg, sizeof(msg));
: }
: }
: else if (nfds == -1)
: {
: printf (“select error: %s\n”, strerror(errno));
: exit (-1);
: }
: }
: return (0);
: }

: /* --------------------------------------------------------- */

: -----
: Andrew Thomas, President, Cogent Real-Time Systems Inc.
: 2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
: Email: andrew@cogent.ca WWW: http://www.cogent.ca

Sean Boudreau <seanb@qnx.com> writes:

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

I know it’s a lot to ask, but can you explain what “handles _IO_NOTIFY
messages correctly” means in the context of my example program? If
you can do it through modifications to the example program, that would
be wonderful. Working in a non-resource-manager context is not so
well documented.

Thanks,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

Andrew Thomas <andrew@cogent.ca> writes:

Sean Boudreau <> seanb@qnx.com> > writes:

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

I know it’s a lot to ask, but can you explain what “handles _IO_NOTIFY
messages correctly” means in the context of my example program? If
you can do it through modifications to the example program, that would
be wonderful. Working in a non-resource-manager context is not so
well documented.

Though I’m still curious, I have found a work-around that lets me
avoid selecting on the COID. The problem was how to MsgReceive from
within a GTK+ program through the GTK main loop. So, the current
problem is solved, but the question remains interesting.

Cheers,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

Andrew Thomas <andrew@cogent.ca> wrote:

Sean Boudreau <> seanb@qnx.com> > writes:

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

I know it’s a lot to ask, but can you explain what “handles _IO_NOTIFY
messages correctly” means in the context of my example program? If
you can do it through modifications to the example program, that would
be wonderful. Working in a non-resource-manager context is not so
well documented.

CAN or CAN NOT select, is depends on the server.

As Sean told you, select(), simply send a message (_IO_NOTIFY) to
the server, sort of saying (if this happened, send this event back
to me). Then select() simply go to block and waiting server to
wake him up.

It’s server’s resposibily to remember the request, and when the request
satuation happened, “send back” (wake up) the client who calls select().

So in your case, your “server” (whoever is doing ChannelCreate(),
and MsgReceive()), have to take a look of the message you received
in MsgReceive(), and then properly handle the _IO_NOTIFY message
(remember the request, compare the satuation …)

It’s kind of difficult to modify your sample cause simply
“select on a coid” do not make sense. (because you CAN NOT
read/write a simple coid)

-xtang

Xiaodan Tang <xtang@qnx.com> writes:

Andrew Thomas <> andrew@cogent.ca> > wrote:
Sean Boudreau <> seanb@qnx.com> > writes:

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

I know it’s a lot to ask, but can you explain what “handles _IO_NOTIFY
messages correctly” means in the context of my example program? If
you can do it through modifications to the example program, that would
be wonderful. Working in a non-resource-manager context is not so
well documented.

CAN or CAN NOT select, is depends on the server.

As Sean told you, select(), simply send a message (_IO_NOTIFY) to
the server, sort of saying (if this happened, send this event back
to me). Then select() simply go to block and waiting server to
wake him up.

It’s server’s resposibily to remember the request, and when the request
satuation happened, “send back” (wake up) the client who calls select().

So in your case, your “server” (whoever is doing ChannelCreate(),
and MsgReceive()), have to take a look of the message you received
in MsgReceive(), and then properly handle the _IO_NOTIFY message
(remember the request, compare the satuation …)

It’s kind of difficult to modify your sample cause simply
“select on a coid” do not make sense. (because you CAN NOT
read/write a simple coid)

The problem is simple, though. Suppose I have a program that needs to
perform select() for its input, and not MsgReceive. This is the case
with a lot of ported software. GTK+ (well, pretty much any X-Windows
based program) is one such example. I have the capability to add a fd
handler, just like in Photon, and I want to use this capability to be
able to “see” native QNX6 messages.

I figured that if I create a connection, then that looks like a file
descriptor, so I select on it to see activity. You are right, though

  • that doesn’t make sense. I really want to select on a channel ID.
    But channel ID’s are not file descriptors. Does this mean I’m stuck?

The real question - is there any way to be able to MsgReceive when the
only interface I have to the event loop is a callback function on a
file descriptor where the loop is implemented in terms of select()?

Cheers,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

Hello Andrew

First off I haven’t actually read your example code but what I’m guessing is
this.

A file descriptor uses a coid but a coid is not necessarily a fd.

select() requires file descriptors.

Bill Caroselli

“Andrew Thomas” <andrew@cogent.ca> wrote in message
news:x73d6i776n.fsf@cogent.ca

Xiaodan Tang <> xtang@qnx.com> > writes:

Andrew Thomas <> andrew@cogent.ca> > wrote:
Sean Boudreau <> seanb@qnx.com> > writes:

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

I know it’s a lot to ask, but can you explain what “handles _IO_NOTIFY
messages correctly” means in the context of my example program? If
you can do it through modifications to the example program, that would
be wonderful. Working in a non-resource-manager context is not so
well documented.

CAN or CAN NOT select, is depends on the server.

As Sean told you, select(), simply send a message (_IO_NOTIFY) to
the server, sort of saying (if this happened, send this event back
to me). Then select() simply go to block and waiting server to
wake him up.

It’s server’s resposibily to remember the request, and when the request
satuation happened, “send back” (wake up) the client who calls select().

So in your case, your “server” (whoever is doing ChannelCreate(),
and MsgReceive()), have to take a look of the message you received
in MsgReceive(), and then properly handle the _IO_NOTIFY message
(remember the request, compare the satuation …)

It’s kind of difficult to modify your sample cause simply
“select on a coid” do not make sense. (because you CAN NOT
read/write a simple coid)

The problem is simple, though. Suppose I have a program that needs to
perform select() for its input, and not MsgReceive. This is the case
with a lot of ported software. GTK+ (well, pretty much any X-Windows
based program) is one such example. I have the capability to add a fd
handler, just like in Photon, and I want to use this capability to be
able to “see” native QNX6 messages.

I figured that if I create a connection, then that looks like a file
descriptor, so I select on it to see activity. You are right, though

  • that doesn’t make sense. I really want to select on a channel ID.
    But channel ID’s are not file descriptors. Does this mean I’m stuck?

The real question - is there any way to be able to MsgReceive when the
only interface I have to the event loop is a callback function on a
file descriptor where the loop is implemented in terms of select()?

Cheers,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: > andrew@cogent.ca > WWW: > http://www.cogent.ca

Andrew Thomas <andrew@cogent.ca> wrote:

Xiaodan Tang <> xtang@qnx.com> > writes:

Andrew Thomas <> andrew@cogent.ca> > wrote:
Sean Boudreau <> seanb@qnx.com> > writes:

select() sends an _IO_NOTIFY message on the fds in the set.
You’re probably send blocked on yourself. You’ll
need another thread that receives on the chid and handles
_IO_NOTIFY messages correctly.

I know it’s a lot to ask, but can you explain what “handles _IO_NOTIFY
messages correctly” means in the context of my example program? If
you can do it through modifications to the example program, that would
be wonderful. Working in a non-resource-manager context is not so
well documented.

CAN or CAN NOT select, is depends on the server.

As Sean told you, select(), simply send a message (_IO_NOTIFY) to
the server, sort of saying (if this happened, send this event back
to me). Then select() simply go to block and waiting server to
wake him up.

It’s server’s resposibily to remember the request, and when the request
satuation happened, “send back” (wake up) the client who calls select().

So in your case, your “server” (whoever is doing ChannelCreate(),
and MsgReceive()), have to take a look of the message you received
in MsgReceive(), and then properly handle the _IO_NOTIFY message
(remember the request, compare the satuation …)

It’s kind of difficult to modify your sample cause simply
“select on a coid” do not make sense. (because you CAN NOT
read/write a simple coid)

The problem is simple, though. Suppose I have a program that needs to
perform select() for its input, and not MsgReceive. This is the case
with a lot of ported software. GTK+ (well, pretty much any X-Windows
based program) is one such example. I have the capability to add a fd
handler, just like in Photon, and I want to use this capability to be
able to “see” native QNX6 messages.

I figured that if I create a connection, then that looks like a file
descriptor, so I select on it to see activity. You are right, though

  • that doesn’t make sense. I really want to select on a channel ID.
    But channel ID’s are not file descriptors. Does this mean I’m stuck?

The real question - is there any way to be able to MsgReceive when the
only interface I have to the event loop is a callback function on a
file descriptor where the loop is implemented in terms of select()?

I sort of understand what you are trying to do. Sth like
_select_receive() in QNX4, right ? :slight_smile:

I can think of several options:

  1. Multi-thread, the MsgReceive() is in different thread, it is not
    controled by your “event loop”.

  2. Have your server thread proper handle the “_IO_NOTIFY”, so you
    could connect to it, and “select(coid)”.

  3. Change the event loop, so it is not select() driven, but MsgReceive()
    (or dispatch_block()) driven. This is the “native QNX6 way”.

-xtang

“Bill Caroselli (Q-TPS)” <qtps@earthlink.net> writes:

Hello Andrew

First off I haven’t actually read your example code but what I’m guessing is
this.

A file descriptor uses a coid but a coid is not necessarily a fd.

select() requires file descriptors.

I get the impression that a coid that is not _NTO_SIDE_CHANNEL is
actually a file descriptor as far as select() is concerned. The first
time I tried this, I used _NTO_SIDE_CHANNEL and select generated a
very reasonable “Out of memory” error, considering that I had passed
in a maximum file descriptor in the billions.

Cheers,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

Xiaodan Tang <xtang@qnx.com> wrote:

I sort of understand what you are trying to do. Sth like
_select_receive() in QNX4, right ? > :slight_smile:

I can think of several options:

  1. Multi-thread, the MsgReceive() is in different thread, it is not
    controled by your “event loop”.

  2. Have your server thread proper handle the “_IO_NOTIFY”, so you
    could connect to it, and “select(coid)”.

  3. Change the event loop, so it is not select() driven, but MsgReceive()
    (or dispatch_block()) driven. This is the “native QNX6 way”.

Or you could define your own select() using select_attach() and a
global dispatch_t pointer. This would let you attach your own stuff to
this common dispatch handle, and have your callbacks called from inside
of select() without having to change the code that calls select().

Now that I think of it, perhaps that’t how our select() should be
implemented… It would certainly make it easier for people to believe
that the dispatch API is the “native QNX6 way” of doing things… :slight_smile:

\

Wojtek Lerch QNX Software Systems Ltd.

Xiaodan Tang <xtang@qnx.com> writes:

I sort of understand what you are trying to do. Sth like
_select_receive() in QNX4, right ? > :slight_smile:

Yes. That’s how I handled this case in QNX4. The library (not in my
control) insisted that the main loop was implemented with select(),
but my IPC all wanted Receive. _select_receive solved this case.

I can think of several options:

  1. Multi-thread, the MsgReceive() is in different thread, it is not
    controled by your “event loop”.

Thread synchronization becomes an issue, and still requires that I
send a message to the main thread somehow. It’s not in general
possible to run code from the library implementing the main loop in a
separate thread. In my case, GTK+, the library is not thread-safe.
If the point of the exercise is to work within the limitations of the
GTK library, then I’m not allowed to modify the main loop. The only
thing I can do is attach a callback function to activity on a file
descriptor, as determined by a call to select() buried deep inside the
GTK library.

  1. Have your server thread proper handle the “_IO_NOTIFY”, so you
    could connect to it, and “select(coid)”.

That doesn’t seem possible without another thread, since select()
would result in a message to myself, and it looks like I really want
to MsgReceive on a chid, which makes me wonder what the point of
select()ing on a coid that I have attached to myself really is. Can
you explain how this would work?

  1. Change the event loop, so it is not select() driven, but
    MsgReceive() (or dispatch_block()) driven. This is the “native
    QNX6 way”.

This turns out to be possible in my particular case. GTK+ (well, glib
really) has a way to override the main loop, allowing me to use a
combination of IO_NOTIFY and MsgReceive to handle both GTK’s
requirements and mine. So, thanks to some forethought in glib, the
problem is solvable. I still don’t have a clear picture of how I
would do this with another GUI library without this main-loop-override
capability.

Cheers,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

Wojtek Lerch <wojtek_l@yahoo.ca> writes:

Or you could define your own select() using select_attach() and a
global dispatch_t pointer. This would let you attach your own stuff
to this common dispatch handle, and have your callbacks called from
inside of select() without having to change the code that calls
select().

Now that I think of it, perhaps that’t how our select() should be
implemented… It would certainly make it easier for people to
believe that the dispatch API is the “native QNX6 way” of doing
things… > :slight_smile:

Of course, you would have to post the source to make sure that the
point got home to the developer community. I look forward to seeing
it. :slight_smile: Seriously, drop-in replacement source for select() would be a
huge benefit to people who are dealing with some classes of porting
problems.

Cheers,
Andrew


Andrew Thomas, President, Cogent Real-Time Systems Inc.
2430 Meadowpine Boulevard, Suite 105, Mississauga, Ontario, Canada L5N 6S2
Email: andrew@cogent.ca WWW: http://www.cogent.ca

Andrew Thomas <andrew@cogent.ca> wrote:

“Bill Caroselli (Q-TPS)” <> qtps@earthlink.net> > writes:
Hello Andrew

First off I haven’t actually read your example code but what I’m guessing is
this.

A file descriptor uses a coid but a coid is not necessarily a fd.

select() requires file descriptors.

I get the impression that a coid that is not _NTO_SIDE_CHANNEL is
actually a file descriptor as far as select() is concerned. The first

Not quite. You have to send an _IO_OPEN message and get a positive
reply before your coid becomes a valid fd. I wouldn’t expect a typical
resource manager to accept an _IO_SELECT without an _IO_OPEN –
particularly if the server owns more than one device or file!!!

time I tried this, I used _NTO_SIDE_CHANNEL and select generated a
very reasonable “Out of memory” error, considering that I had passed
in a maximum file descriptor in the billions.

I’m surprised that your code didn’t crash in FD_SET. Passing an fd
greater than FD_SETSIZE to FD_SET() or friends is “undefined behaviour”.


Wojtek Lerch QNX Software Systems Ltd.