[comp.lang.c] Signal handling on sockets

skp@stl.stc.co.uk (Steve Perryman ) (08/02/90)

I have a signal handling problem I am unable to resolve.

I have set up a signal handler to record whenever a socket receives data
(using the "signal" operation with the SIGIO/SIGPOLL code)


static int trapped ;

void trap()
{
   signal(SIGIO,trap) ;
   trapped++ ;
}



I have a socket set up to read data from the internet and have used the "fcntl"
operation to set the owner process and to allow asynchronous IO so the socket
can invoke the signal handler on receipt of data.


signal(SIGIO,trap) ;
...
...
fcntl(socket,F_SETOWN,getpid()) ;
fcntl(socket,F_SETFL,FASYNC) ;
...


The problem I have is that my test harness sends n messages to the socket in
succession (the real application could receive any number of data items at any
time) and the signal handler is invoked ONCE ONLY. After putting in a loop
to delay the transmission of each data item, the signal handler was invoked
the correct number of times. This suggests a timing/race problem at the
receiving end.

What I would like to know is how to set the signal handler so it acknowledges
every signal regardless of the speed and frequency of receipt of data at the
socket (if this is possible).



Thanks in advance,

Steven Perryman
(skp@stl.stc.co.uk)

richard@aiai.ed.ac.uk (Richard Tobin) (08/03/90)

In article <3271@stl.stc.co.uk> "Steve Perryman " <skp@stl.stc.co.uk> writes:
>The problem I have is that my test harness sends n messages to the socket in
>succession (the real application could receive any number of data items at any
>time) and the signal handler is invoked ONCE ONLY.

Assuming you're using a system with BSD-style signals, you can expect
that (1) SIGIO will be blocked during execution of your signal handler
and (2) if data arrives while the signal is blocked you will receive
precisely one SIGIO when your handler returns, regardless of how
many things arrived during the handler.

If you're reading the data inside the handler, you should read everything
there is, not just one "item".

This will mean that you might get a signal after you've read the
corresponding data, so be prepared for nothing to be waiting.

You can use either select() with a zero timeout or non-blocking i/o
for this.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

lippert@pigpen.rtp.dg.com (Mike Lippert) (08/04/90)

In article <3271@stl.stc.co.uk> "Steve Perryman " <skp@stl.stc.co.uk> writes:
>
>I have a signal handling problem I am unable to resolve.
>
>I have set up a signal handler to record whenever a socket receives data
>(using the "signal" operation with the SIGIO/SIGPOLL code)
... ...
>The problem I have is that my test harness sends n messages to the socket in
>succession (the real application could receive any number of data items at any
>time) and the signal handler is invoked ONCE ONLY. After putting in a loop
>to delay the transmission of each data item, the signal handler was invoked
>the correct number of times. This suggests a timing/race problem at the
>receiving end.
>
>What I would like to know is how to set the signal handler so it acknowledges
>every signal regardless of the speed and frequency of receipt of data at the
>socket (if this is possible).
>
>Steven Perryman
>(skp@stl.stc.co.uk)


Not that this will necessarily solve your problem (I'm just starting
to play w/ UNIX myself) but as I understand it you should use sigset()
instead of signal().  sigset() does not allow the trap routine to be
interrupted by another of the same signal.  It also (I think) does
not require you to reset the signal handler, within the signal handler
as signal() does.

Also I understand signals in unix, the best you can do is be
handling 1 signal and have 1 pended, any more that arrive while 1 is 
pended will be lost, therefore your signal handler should not expect
1 event per signal, but rather 0+ events, ie you should handle
*all* events waiting including *no* events waiting.
--
Michael J. Lippert ---- internet --> lippert@pigpen.rtp.dg.com