Trigger() crashes and remedies revisited

Hi all,

back in october I reported a prob with Trigger() (with libmig4nto) causing a SEGV exception
in the application w/o a stack trace.
(Message-ID:<39F795C2.4C09357E@hentschel.net>)
No solution was found back then, but Sean Boudreau supplied me with the following
code snipped which would work under NTO. After some time off on another project,
I finally tried implementing the suggestion in our app. Here his suggestion first :

#include <sys/neutrino.h>
#include <sys/socket.h>
#include <sys/iomgr.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>

#define CODE 0 //whatever
#define VALUE 0 //whatever

int
main(void)
{
int sfd;
struct sockaddr_in in;
struct sigevent event;
int coid, chid, note, rcvid;
struct _pulse pulse;
struct _msg_info info;
unsigned char buf[100];

if((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror(“socket”);
return 1;
}

memset(&in, 0x00, sizeof in);
in.sin_len = sizeof in;
in.sin_family = AF_INET;
in.sin_addr.s_addr = INADDR_ANY;
in.sin_port = htons(200);

if(bind(sfd, (struct sockaddr *)&in, sizeof in) == -1)
{
perror(“bind”);
return 1;
}

fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL) | O_NONBLOCK);

if((chid = ChannelCreate(0)) == -1)
{
perror(“ChannelCreate”);
return -1;
}

if((coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0)) == -1)
{
perror(“ConnectAttach”);
return 1;
}

event.sigev_notify = SIGEV_PULSE;
event.sigev_coid = coid;
event.sigev_priority = getprio(0);
event.sigev_code = CODE;
event.sigev_value.sival_int = VALUE;

for(;:wink:
{
if((note = ionotify(sfd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event)) == -1)
{
perror(“ionotify”);
return 1;
}

if(!(note & _NOTIFY_COND_INPUT))
{
for(;:wink:
{
if((rcvid = MsgReceive(chid, &pulse, sizeof pulse, &info)) == -1)
{
perror(“MsgReceive”);
return 1;
}

if(pulse.type != _PULSE_TYPE || pulse.subtype != _PULSE_SUBTYPE)
{
MsgError(rcvid, ENOSYS);
continue;
}

if(pulse.code != CODE || pulse.value.sival_int != VALUE)
{
continue;
}
break;
}
}

for(;:wink:
{
/* Process data */
memset(buf, 0x00, sizeof buf);
if(read(sfd, buf, sizeof buf) == -1)
{
break;
}
buf[sizeof buf -1] = ‘\0’;
printf("%s\n", buf);
}

if(errno != EWOULDBLOCK)
{
perror(“read”);
return -1;
}
}
}

Now, the problem is I still need the migration library. This means I
have to block using Receive(). Since the migration lib
blocks pulses, I “fixed” it up to forward pulses to my app :

$ diff /usr/src/qssl/nto/mig4nto.org/mig4nto/ipc_funcs.c ipc_funcs.c
512c512,513
< continue; /* got an unexpected pulse, nothing to do */

return process_msg(rcvid, &rec_msg, (iov_t ) msgmx, parts);
// (TH) continue; /
got an unexpected pulse, nothing to do */

With that I should be able to get the Pulses to my app and distingiush
them by looking for 0 as return from Receive(). Below is the code which
gets called if Receive() would return 0, also “arm_sockets()” get’s
called every time a new socket is created.
Now, what I of course neglected to mention to Sean was that I had to
listen on multiple sockets. Therefore my actual implementation looks like :

#ifdef QNXNTO
static void NTOPulseHandler(void *msg)
{
struct _pulse pulse;

pulse = * (struct _pulse *) msg;

if (pulse.type == !_PULSE_TYPE || pulse.subtype != _PULSE_SUBTYPE)
{
printf(“not a PULSE – help!!! \n”);
arm_sockets();
return;
}

do
{
switch (pulse.code)
{
case PULSECODE :
switch (pulse.value.sival_int)
{
case PULSEVALUE_IO :
printf(“Got PULSE \n”);
SocketEventHandler();
break;

default :
printf(“unknown PULSE VAL \n”);
break;
}
default :
printf(“unknown PULSE CODE \n”);
break;
}
}
while (arm_sockets() == NTO_SCKT_INPUT);
}

extern magic_t magic;

static int arm_sockets(void)
{
int note ;
static int coid = 0;
struct sigevent event;
SOCKET_TYPE *sockNode;

/*

  • make sure we got something
    */
    if (socketRoot == NULL)
    {
    printf("%s: arm_sockets: no Socket Root ! \n", localKBName);
    return NTO_SCKT_ERROR;
    }

/*

  • setup our event structure on which we get notified with
    /
    if (!coid)
    if ((coid = ConnectAttach(0,0,magic.ipc_chid, _NTO_SIDE_CHANNEL, 0)) == -1)
    {
    printf("%s: arm_sockets: ConnectAttach ! \n", localKBName);
    coid = 0;
    return NTO_SCKT_ERROR;
    }
    event.sigev_notify = SIGEV_PULSE; /
    nomen est omen */
    event.sigev_coid = coid;
    event.sigev_priority = getprio(0);
    event.sigev_code = PULSECODE;
    event.sigev_value.sival_int = PULSEVALUE_IO;

sockNode = socketRoot;
while (sockNode)
{
if (note = ionotify(sockNode->socket, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event) == -1)
{
MyLogMsg(errLev, “%s: Error arming sockets : Errno %d ‘%s’\n”, localKBName, errno, sys_errlist[errno]);
return NTO_SCKT_ERROR;
}

if (note & _NOTIFY_COND_INPUT)
return NTO_SCKT_INPUT;

sockNode = NextSocketEntry(sockNode);
}
:
return NTO_SCKT_NOINPUT;
}
#endif

The sockets get initialized and bound somewhere else in the app, and I don’t wan’t
to paste the whole cruft here. Suffice to say that it keeps a linked list
which starts at socketRoot and returns NULL if the last socket has been
reached.

Now, rather unexpectedly, MsgReceive() in libmig4nto exits the app and
stderr prints “I/O possible” when talking to any of the ports bound to sockets in
question.

Why would this cause MsgReceive() exit an application (no SIGSEGV) ?

Any thoughts on what might be wrong ?

Thanks

-Th