There are various techniques to interrupt a socket that I have tried:
NOTE: I am testing this without actual packets being sent from remote
host.
1. Setting SOL_SOCKET / SO_RCVTIMEO with the wanted timeout.
I don't believe this is supported in vxWorks 5.4
If it is, this is the preferred method.
code would look like this:
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
while (1)
{
n= recvfrom(sockfd, recvbuf, RECVBUFSIZE, 0, NULL, NULL);
if (n < 0)
{
if (errno == EWOULDBLOCK)
{
... do something
}
else
{
... recverror
}
}
... handle packet
}
THIS should work, but unless I am actually receiving packets on
the socket, I NEVER get to EWOULDBLOCK I am assuming that SO_RCVTIMEO
is unsupported in vxWorks.
2. Preceeding calls to recvfrom() with calls to select() with timeout on
timeval. This works and I will NOT include code HERE. However, for
both this case and case #1 (above), I am in essense changing the
behavior of my task from one that is truely blocking on the socket
itself (in _sbwait() on an IO semaphore), to one that is in essense
NON-BLOCKING and polling with a resolution of timeval in select().
This solution works for the purposes that I require, however it does
influence the behavior of the waiting task - LESS desirable.
3. Interrupting the socket call by sending a signal to the task.
This solution is the more desirable. However, I am having problems
getting this to work.
Code attached.
void dummy_alarm_handler(int);
SIGVEC myHandlerInfo = {dummy_alarm_handler,0,0} ;
SIGVEC mySavedHandlerInfo ;
int myTaskId;
WDOG_ID myWDId;
/* forward declarations */
LOCAL void myTaskBody (void);
void dummy_alarm_handler(int i)
{
;
}
STATUS myTaskInit (void)
{
.
. assume that the socket is setup as needed
.
sigInit();
sigvec(SIGALRM, &myHandlerInfo, &mySavedHandlerInfo
myTaskId = taskIdSelf() ;
myWDId= wdCreate();
if (myWDId == NULL)
{
printf("\r\nWDCreate failure!!\r\n");
}
return (OK);
}
LOCAL void myTaskBody (void)
{
int pktSize; /* size of recvd packet */
struct sockaddr_in remoteAddr; /* remote transport address */
struct sockaddr_in localAddr; /* local transport address */
char rcvBuf [MY_BUF_SIZE]; /* buffer for input */
int sockSize;
sockSize = sizeof (struct sockaddr_in);
FOREVER
{
if (mySuspendFlag == MYTASK_SUSPEND_SELF_ID)
{
/* turn OFF suspend Flag for next time */
mySuspendFlag= 0;
printf("actually suspended HERE !!");
taskSuspend(taskIdSelf());
printf("Resumed from HERE !!\r\n");
}
if ( (pktSize = recvfrom (mySocket, rcvBuf, MY_BUF_SIZE, 0,
(struct sockaddr *) &remoteAddr, &sockSize))
<= 0 )
{
/* If pktSize is error (<0) or other printerr data */
if (pktSize < 0 )
{
switch (errno)
{
case EWOULDBLOCK:
printf("recvfrom TIMEOUT !!");
break;
case EINTR:
printf("recvfrom INTR via alarm !!");
break;
default:
printf("recvfrom OTHER errno !!");
break;
}
}
else
{
printf("recvfrom == 0 (No Packet Data to Process)");
}
continue;
}
sockSize = sizeof (struct sockaddr_in);
getsockname (mySocket, (struct sockaddr *) &localAddr, &sockSize);
printf("Received packet...");
processPacket (pktSize, rcvBuf, &remoteAddr, &localAddr, &mySocket);
}
}
int myWDRoutine(void)
{
kill(myTaskId, SIGALRM);
return (0);
}
void myTaskSelfKill(void)
{
wdStart(myWDId, 1300, myWDRoutine, 0) ;
}
Calling myTaskSelfKill starts the wdTimer correctly, However for some
reason the call to Kill in myWdRoutine() has no affect, and therefore,
I never get to interrupt my task. I checked with wdShow() to ensure
that the WD was setup with the correct function. It seams as if sigvec
has NO EFFECT !! If I call sigvec(SIGALRM, 0, &tempSIGVEC) from shell
there doesn't seem to be anything set to tempSIGVEC !! Contents are
all 0.
Signals don't seem to be setup appropraitely!
myTask remains locked on the semaphore in recvfrom() ...
Am I missing anything here?
Any/all help would be appreciated.
Thanks.
-Mike
ioctl (sockFd, FIOCANCEL, 0);
this should make the read() or recvfrom() return with an error immediately,
and it is permitted to make this call from an ISR, if I recall correctly.
-- HTH
P.S. How's life at ECI Telecom these days ?
-----------------------------------------------------------------------
Leonid Rosenboim Visit:
http://gamla.org.il/english/index.htm
Consultant Email: my first name at consultant dot com
"mbe...@outthere.com" <mbe...@ecitele.com> wrote in message
news:a7a5bf22.02102...@posting.google.com...
For whatever reason, this ioctl() call also fails, and therefore
doesn't release the the recvfrom call.
So far it looks as if I'll have to remain with my select()
solution. Even though it is the least desirable !!
-Mike
The original code that I posted uses the watchdog to send
SIGALRM to the ping sender, not the receiver. The ping sender
task is the one spawned at entrypoint start_pinging, and it is
waiting at a call to pause() for a signal to be received. The
receiver of those pings is the task with entrypoint receive_pings.
The check that is in my example for EINTR after recvfrom is just
standard error-checking practice for error returns from a recvfrom
call.
> If I call sigvec(SIGALRM, 0, &tempSIGVEC) from shell
> there doesn't seem to be anything set to tempSIGVEC !! Contents are
> all 0.
When you call sigvec from the shell, aren't you operating on the
signal handlers for the shell task? I don't know if what you are
seeing there is not expected.
I would try a staged approach. Put a logmsg call in your watchdog
routine. Is it being called as expected? I know that you say it
is being set up correctly, but is it ever actually called?
Then try several of the VxWorks calls to get a signal handler
registered by the task doing the recvfrom. Try to get a signal
to a task that is not in recvfrom, but rather doing a pause().
Break your problem down into subproblems. Determine what you can
and can't get to work. Then you can ask a more specific question
once you have determined exactly where your implementation breaks
down.
Regards,
Chuck Meade
The PTR Group, Inc.
www.ThePTRGroup.com
> Newsgroups: comp.os.vxworks
> Subject: Interrupting blocked I/O recvfrom calls
> Date: 27 Oct 2002 05:23:22 -0800
> From: mbe...@ecitele.com (mbe...@outthere.com)
> Organization: http://groups.google.com/
> Message-ID: <a7a5bf22.02102...@posting.google.com>
> - -Mike