MsgDeliverEvent/channel/name_open problems

I’m having conceptual problems (apparently) and actual problems
(really). I’m not able to receive the pulse sent by MsgDeliverEvent()
in the “client” below. Conceptually, server does rcvid=MsgReceive(),
client does MsgSend(), server calls MsgDeliverEvent(rcvid, …) which
supposedly sends a pulse to the client which hasn’t even created a
channel yet. Where does the pulse go, then? In order for the client
to actually receive the pulse, a channel has to be given in the
MsgReceive(). I tried just using “1”, guessing that a channel might
have been automagically created by doing a MsgSend (doesn’t make much
sense but…) No go… MsgReceive() fails with “invalid process”.
When i call ChannelCreate() (which returns 2) and use that in the
MsgReceive(), it just blocks, although the MsgDeliverEvent() completed
without error. Apparently that’s not the right channel.

I run the above test by running the server first, then running the
client with the process id and channel id of the server passed in on
the command line. This way at least the first Send/Receive/Reply all
work. But if i run the client with no args, using the connection id
obtained from name_open(), the MsgSend fails with ENOSYS, which isn’t
even listed as an error for MsgSend.

This is all very unexpectedly puzzling.

// “Server”

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

main( int argc, char *argv[] )
{
int retstat;
name_attach_t *na;
char buf[512];
struct _msg_info info;

if ( argc > 1 )
retstat = atoi( argv[1] );

na = name_attach( 0, “craig”, 0 );
if ( na )
{
printf(“process id: %d\n”, getpid());
printf(“channel id: %d\n”, na->chid);
// printf(“mount id: %d\n”, na->mntid); // always seems to be 0
}
else
printf(“name_attach fail: %s (%d)\n”, strerror(errno), errno);

while ( 1 )
{
int rcvid = MsgReceive( na->chid, buf, sizeof(buf), &info );
if ( rcvid > 0 )
{
printf(“rcvd: `%s’ (rcvid: %d)\n”, buf, rcvid);

printf(“pid: %d\n”, info.pid);
printf(“tid: %d\n”, info.tid);
printf(“chid: %d\n”, info.chid);
printf(“scoid: %d\n”, info.scoid);
printf(“coid: %d\n”, info.coid);
printf(“msglen: %d\n”, info.msglen);

strcpy( buf, “I think i know” );
printf(“reply with: %s (status: %d)\n”, buf, retstat);
if ( MsgReply( rcvid, retstat, buf, strlen(buf)+1 ) == -1 )
fprintf(stderr, “MsgReply fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( rcvid == 0 )
{
printf(“received pulse\n”);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( rcvid > 0 )
{
struct sigevent event;
event.sigev_coid = rcvid;
event.sigev_code = 13;
event.sigev_value.sival_int = 0x06660666;
printf(“Calling MsgDeliverEvent(%d, …)\n”, rcvid);
if ( MsgDeliverEvent(rcvid, &event) == -1 )
fprintf(stderr, “MsgDeliverEvent fail: %s (%d)\n”, strerror(errno), errno);
}
}
return 0;
}

// “Client”

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

int main( int argc, char *argv[] )
{
int coid;
char resp[512];

if ( argc == 1 )
{
int coid = name_open( “craig”, 0 );
if ( coid > 0 )
printf(“connection id: %d\n”, coid);
else
printf(“name_open fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( argc > 2 )
{
int pid = atoi(argv[1]);
int chid = atoi(argv[2]);
printf(“attaching to pid %d, chid %d\n”, pid, chid);
coid = ConnectAttach( 0, pid, chid, _NTO_SIDE_CHANNEL, 0 );
if ( coid > 0 )
printf(“connection id: %d\n”, coid);
else
printf(“ConnectAttach fail: %s (%d)\n”, strerror(errno), errno);
}
else
printf(“Need args\n”);

char *msg = “Whose woods these are”;
int status = MsgSend( coid, msg, strlen(msg)+1, resp, sizeof(resp) );
if ( status == -1 )
fprintf(stderr, “MsgSend fail: %s (%d)\n”, strerror(errno), errno);
else
printf(“resp: %s (status: %d)\n”, resp, status);


int chid = ChannelCreate(0);
printf(“Created channel %d\n”, chid);
char buf[512];
struct _msg_info info;
int rcvid = MsgReceive( chid, buf, sizeof(buf), &info );
if ( rcvid > 0 )
printf(“Received msg\n”);
else if ( rcvid == 0 )
{
printf(“Received pulse\n”);
struct _pulse *pp = (_pulse *)buf;
printf(“code\n”, pp->code);
printf(“data\n”, pp->value.sival_int);
printf(“scoid\n”, pp->scoid);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( argc == 1 )
name_close(coid);
ConnectDetach(coid);
printf(“exiting…\n”);
return 0;
}

Craig Duncan <craig@duncan.nycap.rr.com> wrote:

I’m having conceptual problems (apparently) and actual problems
(really). I’m not able to receive the pulse sent by MsgDeliverEvent()
in the “client” below. Conceptually, server does rcvid=MsgReceive(),
client does MsgSend(), server calls MsgDeliverEvent(rcvid, …) which
supposedly sends a pulse to the client which hasn’t even created a
channel yet. Where does the pulse go, then? In order for the client
to actually receive the pulse, a channel has to be given in the
MsgReceive(). I tried just using “1”, guessing that a channel might
have been automagically created by doing a MsgSend (doesn’t make much
sense but…) No go… MsgReceive() fails with “invalid process”.
When i call ChannelCreate() (which returns 2) and use that in the
MsgReceive(), it just blocks, although the MsgDeliverEvent() completed
without error. Apparently that’s not the right channel.

The idea of “MsgDeliverEvent()” is a “client side notification”.

In general it works like this:

  1. the client will prepare the “event”, send it to server via
    MsgSend(), it’s sort of saying, “if THIS happened, give be back
    THIS event”.

  2. the server then copy the “event” and “rcvid” in somewhere, and
    MsgReply() to client. Means “OK, I got it”.

  3. and once the client required condition IS true, the server then
    MsgDelieverEvent() the event back to client.

You should note a “event” could be a pulse, it also could be
something else (check /usr/include/sys/siginfo.h).

So, if the client wnat a pulse back, it have to “prepare” the
pulse event. Which means, it had to:

  1. create a channel()
  2. ConnectAttach() to the channel (yes, attach to channle created
    itself).
  3. create an event with the “connection id”, the “pulse code”
    (which should be in range of _PULSE_CODE_MINAVAIL and
    _PULSE_CODE_MAXAVAIL), the “value” which will would be carried
    by the pulse.
  4. MsgSend() this event to server.

The server then remember the rcvid, and this event, and call
MsgDelieverEvent() to deliever this event back.

Of cause the client must have a thread “MsgReceive()” or
“MsgReceivePulse()” on the channel created in 1), so that
it can receive the pulse delievered by server.

Hope this could help.

-xtang


I run the above test by running the server first, then running the
client with the process id and channel id of the server passed in on
the command line. This way at least the first Send/Receive/Reply all
work. But if i run the client with no args, using the connection id
obtained from name_open(), the MsgSend fails with ENOSYS, which isn’t
even listed as an error for MsgSend.

This is all very unexpectedly puzzling.

// “Server”

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

main( int argc, char *argv[] )
{
int retstat;
name_attach_t *na;
char buf[512];
struct _msg_info info;

if ( argc > 1 )
retstat = atoi( argv[1] );

na = name_attach( 0, “craig”, 0 );
if ( na )
{
printf(“process id: %d\n”, getpid());
printf(“channel id: %d\n”, na->chid);
// printf(“mount id: %d\n”, na->mntid); // always seems to be 0
}
else
printf(“name_attach fail: %s (%d)\n”, strerror(errno), errno);

while ( 1 )
{
int rcvid = MsgReceive( na->chid, buf, sizeof(buf), &info );
if ( rcvid > 0 )
{
printf(“rcvd: `%s’ (rcvid: %d)\n”, buf, rcvid);

printf(“pid: %d\n”, info.pid);
printf(“tid: %d\n”, info.tid);
printf(“chid: %d\n”, info.chid);
printf(“scoid: %d\n”, info.scoid);
printf(“coid: %d\n”, info.coid);
printf(“msglen: %d\n”, info.msglen);

strcpy( buf, “I think i know” );
printf(“reply with: %s (status: %d)\n”, buf, retstat);
if ( MsgReply( rcvid, retstat, buf, strlen(buf)+1 ) == -1 )
fprintf(stderr, “MsgReply fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( rcvid == 0 )
{
printf(“received pulse\n”);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( rcvid > 0 )
{
struct sigevent event;
event.sigev_coid = rcvid;
event.sigev_code = 13;
event.sigev_value.sival_int = 0x06660666;
printf(“Calling MsgDeliverEvent(%d, …)\n”, rcvid);
if ( MsgDeliverEvent(rcvid, &event) == -1 )
fprintf(stderr, “MsgDeliverEvent fail: %s (%d)\n”, strerror(errno), errno);
}
}
return 0;
}

// “Client”

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

int main( int argc, char *argv[] )
{
int coid;
char resp[512];

if ( argc == 1 )
{
int coid = name_open( “craig”, 0 );
if ( coid > 0 )
printf(“connection id: %d\n”, coid);
else
printf(“name_open fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( argc > 2 )
{
int pid = atoi(argv[1]);
int chid = atoi(argv[2]);
printf(“attaching to pid %d, chid %d\n”, pid, chid);
coid = ConnectAttach( 0, pid, chid, _NTO_SIDE_CHANNEL, 0 );
if ( coid > 0 )
printf(“connection id: %d\n”, coid);
else
printf(“ConnectAttach fail: %s (%d)\n”, strerror(errno), errno);
}
else
printf(“Need args\n”);

char *msg = “Whose woods these are”;
int status = MsgSend( coid, msg, strlen(msg)+1, resp, sizeof(resp) );
if ( status == -1 )
fprintf(stderr, “MsgSend fail: %s (%d)\n”, strerror(errno), errno);
else
printf(“resp: %s (status: %d)\n”, resp, status);


int chid = ChannelCreate(0);
printf(“Created channel %d\n”, chid);
char buf[512];
struct _msg_info info;
int rcvid = MsgReceive( chid, buf, sizeof(buf), &info );
if ( rcvid > 0 )
printf(“Received msg\n”);
else if ( rcvid == 0 )
{
printf(“Received pulse\n”);
struct _pulse *pp = (_pulse *)buf;
printf(“code\n”, pp->code);
printf(“data\n”, pp->value.sival_int);
printf(“scoid\n”, pp->scoid);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( argc == 1 )
name_close(coid);
ConnectDetach(coid);
printf(“exiting…\n”);
return 0;
}

Thanks to Xiaodan for explaining MsgDeliverEvent() a little more. My
name_open problem was a stupid programming error on my part. I think
its impossible to understand MsgDeliverEvent() from the documentation,
but i found the following response by Xiaodan in a previous exchange
very helpful:

A “rcvid” is an id valued “ONLY” to the a server (who did the
MsgReceive). It represents a “client” who is currently talking to
the server. It guaranteed the server that if server “MsgReply()” on
the rcvid, it will reply to whoever did the MsgSend().

So, in your sample below, (I suppose run_client_threads() actually
use pthread_crete() to create 10 threads), you will got 10 different
rcvid, and no matter what order you MsgReply(), if you
“MsgReply(rcvid[5], …)”, you always reply to the fifth thread who
did the MsgSend().

It is strictly saying you “CAN NOT MsgReply()” to same rcvid twice
without MsgReceive() it first. After a “MsgReply(rcvid, …)”, the
rcvid is no longer valued to the server any more.

ONLY EXCEPTION is MsgDelieverEvent(). MsgDelieverEvent() is a
“backword” message passing, it start from “server”, target to
“client”. It is used if the client do not wish to blocking on
server, or 2 process must exchange message between them.

The use of MsgDelieverEvent() usually like this:

  1. he then build up a “event”. (in case the “event” is a pulse,
    the client have to first create a channel, and ConnectAttach()
    to it to get the coid store in “event”).

  2. he did a MsgSend() to the server, saying “if , send back to me”

  3. the server then “remember” both the “event and rcvid”, and
    MsgReply(rcvid) to unblock client.

  4. if the sever find the condition client request is true, it
    will then MsgDelieverEvent(rcvid, theEvent) to notify the client.

The MsgDelieverEvent() take a rcvid, because in case the “event” is
a thread related one (SIGEV_SIGNAL_THREAD, etc), the event will
delievered to the client thread who did the MsgSend() in step 2. In
case of a SIGEV_PULSE event, the event deliever to the connection,
pointed by the sigev_coid member. (in this case, the rcvid is only
used to confirm that the clinet have a connection with server)

So, taking all this into account, i have the following programs, which
demonstrate MsgDeliverEvent failing with EINVAL.

Client:

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

int main( int argc, char *argv[] )
{
int coid;
char resp[512];

if ( argc == 1 )
{
coid = name_open( “craig”, 0 );
if ( coid == -1 )
printf(“name_open fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( argc > 2 )
{
int pid = atoi(argv[1]);
int chid = atoi(argv[2]);
printf(“attaching to pid %d, chid %d\n”, pid, chid);
coid = ConnectAttach( 0, pid, chid, _NTO_SIDE_CHANNEL, 0 );
if ( coid == -1 )
printf(“ConnectAttach fail: %s (%d)\n”, strerror(errno), errno);
}
else
{
printf(“Need args\n”);
return 0;
}

printf(“connection id: %d\n”, coid);

int pchid = ChannelCreate(0);
int pcoid = ConnectAttach( 0, getpid(), pchid, _NTO_SIDE_CHANNEL, 0 );
printf(“Created channel %d, coid %d\n”, pchid, pcoid);

printf(“Sending sigevent\n”);
struct sigevent event;
event.sigev_coid = pcoid;
event.sigev_code = 13;
event.sigev_value.sival_int = 0x06660666;

int status = MsgSend( coid, &event, sizeof(event), resp, sizeof(resp) );
if ( status == -1 )
fprintf(stderr, “MsgSend fail: %s (%d)\n”, strerror(errno), errno);
else
printf(“resp: %s (status: %d)\n”, resp, status);

printf(“Waiting to receive event\n”);
char buf[512];
struct _msg_info info;
int rcvid = MsgReceive( pchid, buf, sizeof(buf), &info );
if ( rcvid > 0 )
printf(“Received msg\n”);
else if ( rcvid == 0 )
{
printf(“Received pulse\n”);
struct _pulse *pp = (_pulse *)buf;
printf(“code: %d\n”, pp->code);
printf(“data: %d\n”, pp->value.sival_int);
printf(“scoid: %d\n”, pp->scoid);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( argc == 1 )
name_close(coid);
else
ConnectDetach(coid);
printf(“exiting…\n”);
return 0;
}

Server:

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

int
main( int argc, char *argv[] )
{
int retstat = 0, rcvdEvent = 0, chid = 0;
name_attach_t *na;
char buf[512], buf2[512];
struct _msg_info info;

na = name_attach( 0, “craig”, 0 );
if ( na )
{
chid = na->chid;
}
else
printf(“name_attach fail: %s (%d)\n”, strerror(errno), errno);

printf(“process id: %d\n”, getpid());
printf(“channel id: %d\n”, chid);

for ( int i = 0; i < 3; i++ )
{
printf(“Waiting for msg\n”);
int rcvid = MsgReceive( chid, buf, sizeof(buf), &info );
printf(“Received msg (rcvid: %d)\n”, rcvid);

if ( rcvid > 0 )
{
printf(“pid: %d\n”, info.pid);
printf(“tid: %d\n”, info.tid);
printf(“chid: %d\n”, info.chid);
printf(“scoid: %d\n”, info.scoid);
printf(“coid: %d\n”, info.coid);
printf(“msglen: %d\n”, info.msglen);

if ( info.msglen == sizeof(sigevent) )
{
sprintf( buf2, “Server rcvd sigevent (%d bytes)”, info.msglen );
printf(“rcvd sigevent\n”);
rcvdEvent = 1;
}
else
{
sprintf( buf2, “Server rcvd %d byte msg”, info.msglen );
printf(“rcvd %d bytes\n”, info.msglen);
}

printf(“reply with: %s (status: %d)\n”, buf2, retstat);
if ( MsgReply( rcvid, retstat, buf2, strlen(buf2)+1 ) == -1 )
fprintf(stderr, “MsgReply fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( rcvid == 0 )
{
printf(“received pulse\n”);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( rcvid > 0 && rcvdEvent )
{
struct sigevent *event = (struct sigevent *)&buf;

printf(“Received event\n”);
printf(“coid: %d\n”, event->sigev_coid);
printf(“code: %d\n”, event->sigev_code);
printf(“data: %d\n”, event->sigev_value.sival_int);

printf(“Calling MsgDeliverEvent(%d, …)\n”, rcvid);
if ( MsgDeliverEvent(rcvid, event) == -1 )
fprintf(stderr, “MsgDeliverEvent fail: %s (%d)\n”,
strerror(errno), errno);
}
}
name_detach(na, 0);
return 0;
}

Output:

root$ ./client
connection id: 1073741825
Created channel 2, coid 1073741827
Sending sigevent
resp: Server rcvd sigevent (16 bytes) (status: 0)
Waiting to receive event

root$ ./server
process id: 81342505
channel id: 1
Waiting for msg
Received msg (rcvid: 3)
pid: 81346603
tid: 1
chid: 1
scoid: 1073741827
coid: 1073741825
msglen: 16
rcvd sigevent
reply with: Server rcvd sigevent (16 bytes) (status: 0)
Received event
coid: 1073741827
code: 13
data: 107349606
Calling MsgDeliverEvent(3, …)
MsgDeliverEvent fail: Invalid argument (22)
Waiting for msg

Instead of initialize a event like this:

struct sigevent event;
event.sigev_coid = pcoid;
event.sigev_code = 13;
event.sigev_value.sival_int = 0x06660666;

You should really use:

struct sigevent event;
SIGEV_PULSE_INIT(&event, pcoid, SIGEV_PULSE_PRIO_INHERIT, 13, 0x06660666);

This macro defined in /usr/include/sys/siginfo.h, take a look of it
you will see there are some other members you need to initialize.

-xtang

Craig Duncan <craig@duncan.nycap.rr.com> wrote:

Thanks to Xiaodan for explaining MsgDeliverEvent() a little more. My
name_open problem was a stupid programming error on my part. I think
its impossible to understand MsgDeliverEvent() from the documentation,
but i found the following response by Xiaodan in a previous exchange
very helpful:

A “rcvid” is an id valued “ONLY” to the a server (who did the
MsgReceive). It represents a “client” who is currently talking to
the server. It guaranteed the server that if server “MsgReply()” on
the rcvid, it will reply to whoever did the MsgSend().

So, in your sample below, (I suppose run_client_threads() actually
use pthread_crete() to create 10 threads), you will got 10 different
rcvid, and no matter what order you MsgReply(), if you
“MsgReply(rcvid[5], …)”, you always reply to the fifth thread who
did the MsgSend().

It is strictly saying you “CAN NOT MsgReply()” to same rcvid twice
without MsgReceive() it first. After a “MsgReply(rcvid, …)”, the
rcvid is no longer valued to the server any more.

ONLY EXCEPTION is MsgDelieverEvent(). MsgDelieverEvent() is a
“backword” message passing, it start from “server”, target to
“client”. It is used if the client do not wish to blocking on
server, or 2 process must exchange message between them.

The use of MsgDelieverEvent() usually like this:

  1. he then build up a “event”. (in case the “event” is a pulse,
    the client have to first create a channel, and ConnectAttach()
    to it to get the coid store in “event”).

  2. he did a MsgSend() to the server, saying “if , send back to me”

  3. the server then “remember” both the “event and rcvid”, and
    MsgReply(rcvid) to unblock client.

  4. if the sever find the condition client request is true, it
    will then MsgDelieverEvent(rcvid, theEvent) to notify the client.

The MsgDelieverEvent() take a rcvid, because in case the “event” is
a thread related one (SIGEV_SIGNAL_THREAD, etc), the event will
delievered to the client thread who did the MsgSend() in step 2. In
case of a SIGEV_PULSE event, the event deliever to the connection,
pointed by the sigev_coid member. (in this case, the rcvid is only
used to confirm that the clinet have a connection with server)

So, taking all this into account, i have the following programs, which
demonstrate MsgDeliverEvent failing with EINVAL.

Client:

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

int main( int argc, char *argv[] )
{
int coid;
char resp[512];

if ( argc == 1 )
{
coid = name_open( “craig”, 0 );
if ( coid == -1 )
printf(“name_open fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( argc > 2 )
{
int pid = atoi(argv[1]);
int chid = atoi(argv[2]);
printf(“attaching to pid %d, chid %d\n”, pid, chid);
coid = ConnectAttach( 0, pid, chid, _NTO_SIDE_CHANNEL, 0 );
if ( coid == -1 )
printf(“ConnectAttach fail: %s (%d)\n”, strerror(errno), errno);
}
else
{
printf(“Need args\n”);
return 0;
}

printf(“connection id: %d\n”, coid);

int pchid = ChannelCreate(0);
int pcoid = ConnectAttach( 0, getpid(), pchid, _NTO_SIDE_CHANNEL, 0 );
printf(“Created channel %d, coid %d\n”, pchid, pcoid);

printf(“Sending sigevent\n”);
struct sigevent event;
event.sigev_coid = pcoid;
event.sigev_code = 13;
event.sigev_value.sival_int = 0x06660666;

int status = MsgSend( coid, &event, sizeof(event), resp, sizeof(resp) );
if ( status == -1 )
fprintf(stderr, “MsgSend fail: %s (%d)\n”, strerror(errno), errno);
else
printf(“resp: %s (status: %d)\n”, resp, status);

printf(“Waiting to receive event\n”);
char buf[512];
struct _msg_info info;
int rcvid = MsgReceive( pchid, buf, sizeof(buf), &info );
if ( rcvid > 0 )
printf(“Received msg\n”);
else if ( rcvid == 0 )
{
printf(“Received pulse\n”);
struct _pulse *pp = (_pulse *)buf;
printf(“code: %d\n”, pp->code);
printf(“data: %d\n”, pp->value.sival_int);
printf(“scoid: %d\n”, pp->scoid);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( argc == 1 )
name_close(coid);
else
ConnectDetach(coid);
printf(“exiting…\n”);
return 0;
}

Server:

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

int
main( int argc, char *argv[] )
{
int retstat = 0, rcvdEvent = 0, chid = 0;
name_attach_t *na;
char buf[512], buf2[512];
struct _msg_info info;

na = name_attach( 0, “craig”, 0 );
if ( na )
{
chid = na->chid;
}
else
printf(“name_attach fail: %s (%d)\n”, strerror(errno), errno);

printf(“process id: %d\n”, getpid());
printf(“channel id: %d\n”, chid);

for ( int i = 0; i < 3; i++ )
{
printf(“Waiting for msg\n”);
int rcvid = MsgReceive( chid, buf, sizeof(buf), &info );
printf(“Received msg (rcvid: %d)\n”, rcvid);

if ( rcvid > 0 )
{
printf(“pid: %d\n”, info.pid);
printf(“tid: %d\n”, info.tid);
printf(“chid: %d\n”, info.chid);
printf(“scoid: %d\n”, info.scoid);
printf(“coid: %d\n”, info.coid);
printf(“msglen: %d\n”, info.msglen);

if ( info.msglen == sizeof(sigevent) )
{
sprintf( buf2, “Server rcvd sigevent (%d bytes)”, info.msglen );
printf(“rcvd sigevent\n”);
rcvdEvent = 1;
}
else
{
sprintf( buf2, “Server rcvd %d byte msg”, info.msglen );
printf(“rcvd %d bytes\n”, info.msglen);
}

printf(“reply with: %s (status: %d)\n”, buf2, retstat);
if ( MsgReply( rcvid, retstat, buf2, strlen(buf2)+1 ) == -1 )
fprintf(stderr, “MsgReply fail: %s (%d)\n”, strerror(errno), errno);
}
else if ( rcvid == 0 )
{
printf(“received pulse\n”);
}
else
fprintf(stderr, “MsgReceive fail: %s (%d)\n”, strerror(errno), errno);

if ( rcvid > 0 && rcvdEvent )
{
struct sigevent *event = (struct sigevent *)&buf;

printf(“Received event\n”);
printf(“coid: %d\n”, event->sigev_coid);
printf(“code: %d\n”, event->sigev_code);
printf(“data: %d\n”, event->sigev_value.sival_int);

printf(“Calling MsgDeliverEvent(%d, …)\n”, rcvid);
if ( MsgDeliverEvent(rcvid, event) == -1 )
fprintf(stderr, “MsgDeliverEvent fail: %s (%d)\n”,
strerror(errno), errno);
}
}
name_detach(na, 0);
return 0;
}

Output:

root$ ./client
connection id: 1073741825
Created channel 2, coid 1073741827
Sending sigevent
resp: Server rcvd sigevent (16 bytes) (status: 0)
Waiting to receive event

root$ ./server
process id: 81342505
channel id: 1
Waiting for msg
Received msg (rcvid: 3)
pid: 81346603
tid: 1
chid: 1
scoid: 1073741827
coid: 1073741825
msglen: 16
rcvd sigevent
reply with: Server rcvd sigevent (16 bytes) (status: 0)
Received event
coid: 1073741827
code: 13
data: 107349606
Calling MsgDeliverEvent(3, …)
MsgDeliverEvent fail: Invalid argument (22)
Waiting for msg

Craig Duncan <craig@duncan.nycap.rr.com> wrote:
: Thanks to Xiaodan for explaining MsgDeliverEvent() a little more. My
: name_open problem was a stupid programming error on my part. I think
: its impossible to understand MsgDeliverEvent() from the documentation,
: but i found the following response by Xiaodan in a previous exchange
: very helpful:

I’ll see what I can do to improve the docs. Thanks for the suggestion.


Steve Reid stever@qnx.com
TechPubs (Technical Publications)
QNX Software Systems