ChannelCreate after spawn

QNX 6.2

In a parent process I have:


// Start process
*process_id = spawnl(P_NOWAITO, path, “”, NULL);
assert( *process_id != FAILURE );

// Wait for process to set up channel
delay(50);

// Set process priority
param.sched_priority = priority;
return_value = sched_setscheduler(*process_id, SCHED_FIFO, &param);
assert( return_value != FAILURE );

// Connect to process
*connection_id = ConnectAttach( ND_LOCAL_NODE, *process_id, CHANNEL_ID,
_NTO_SIDE_CHANNEL, 0);
assert( *connection_id != FAILURE );




In the child I have:


int main(int argc, char **argv)
{
// Declarations etc

control_chid = 0;
control_chid = ChannelCreate(_NTO_CHF_UNBLOCK);
assert( control_chid != FAILURE );




If I take out the delay(50) line then this fails I assume because the child
process has not yet created a channel to ConnectAttach() to. Is there a
better/proper way to deal with this? nb. ChannelCreate() is the first
function that the child calls.

pdaj <paul.jones@bnc.ox.ac.uk> wrote:

QNX 6.2

In a parent process I have:


// Start process
*process_id = spawnl(P_NOWAITO, path, “”, NULL);
assert( *process_id != FAILURE );

// Wait for process to set up channel
delay(50);

// Set process priority
param.sched_priority = priority;
return_value = sched_setscheduler(*process_id, SCHED_FIFO, &param);
assert( return_value != FAILURE );

// Connect to process
*connection_id = ConnectAttach( ND_LOCAL_NODE, *process_id, CHANNEL_ID,
_NTO_SIDE_CHANNEL, 0);
assert( *connection_id != FAILURE );


How do you know what channel id the child is going to get? Using
CHANNEL_ID suggests that you know at compile time which dynamic id
the OS will assign at run time.

(yes, we give chids out in order 1,2,3, etc…but this is discovered
behaviour, not documented behaviour – and I think it is explicitly
undocumented – you’re not supposed to depend on it. It is kind of
like doing:

if (open(…) != -1)
write(3,buf, data )

(Except worse, as I think that fd are documented as being given out
in lowest available fd given first order.))

In the child I have:


int main(int argc, char **argv)
{
// Declarations etc

control_chid = 0;
control_chid = ChannelCreate(_NTO_CHF_UNBLOCK);
assert( control_chid != FAILURE );




If I take out the delay(50) line then this fails I assume because the child
process has not yet created a channel to ConnectAttach() to. Is there a
better/proper way to deal with this? nb. ChannelCreate() is the first
function that the child calls.

There is no SIMPLE better way. In fact, you’re way could fail sometimes…
your guess of delay time might not be long enough… something pre-empts
the child before it can ChannelCreate() and you don’t wait long enough…
etc.

Slightly better is to loop your delay & ConnectAttach(), maybe giving
up after a certain number of retries or something similar.
Of course, this doesn’t deal with the issue of how does the parent know
the child’s chid.

For the chid issue, it would be better for the child to use a
name_attach() to register the name, and for the parent to do a
looped with delay name_open() until it succeeds or gives up.

Or, the parent could block in a sigwaitinfo() call, and the child
could send the parent a signal after the ChannelCreate(), with the
chid as data carried by the signal. This would avoid the loop and
the child could use ChannelCreate() rather than name_attach() if
you didn’t want to use the name lookup stuff.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

I had a very similar question a while back. You can check the thread
“Communications server architecture” in q.p.qnxrtp.os if you like. In short
though, I wait for the client to send me a pulse with the channel id, to
which the server then connects.

Here’s a handy little snippet of code for the server:
struct _pulse pulse;
int nRcvId = MsgReceive_r( nChId, &pulse, sizeof( pulse), NULL);
if( nRcvId == 0 && pulse.code == CLIENT_ADVERTISE) {
struct _client_info info;
// client is advertising
ConnectClientInfo_r( pulse.scoid, &info, 0);
coid = ConnectAttach_r(
info.nd, info.pid, pulse.value.sival_int,
_NTO_SIDE_CHANNEL, 0);
}

Cheers,
Shaun

Shaun Jackman <sjackman@nospam.vortek.com> wrote:

I had a very similar question a while back. You can check the thread
“Communications server architecture” in q.p.qnxrtp.os if you like. In short
though, I wait for the client to send me a pulse with the channel id, to
which the server then connects.

Here’s a handy little snippet of code for the server:
struct _pulse pulse;
int nRcvId = MsgReceive_r( nChId, &pulse, sizeof( pulse), NULL);
if( nRcvId == 0 && pulse.code == CLIENT_ADVERTISE) {
struct _client_info info;
// client is advertising
ConnectClientInfo_r( pulse.scoid, &info, 0);
coid = ConnectAttach_r(
info.nd, info.pid, pulse.value.sival_int,
_NTO_SIDE_CHANNEL, 0);
}

That works too, if the parent has a channel, and passes the chid to
the client in the command line arguments or something similar.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.