Sockets and interrupt driven I/O

Sockets and interrupt driven I/O

Post by Sean Holdswor » Tue, 27 Feb 1990 21:24:22



I am currently struggling with sockets under SUNOS 3.5. The basic problem is
trying to implement interrupt driven I/O rather than use the select call
which I can't use because of other activity within the same process.

The current state of play is that I've succeeded in arranging to have the
arrival of data at a socket signalled by SIGIO. This was done using the usual
incantations for setting the owner of the socket to be the process group of
the process to which the socket belongs, making the socket non-blocking and
setting its ASYNC flag.

The problem arises because if I write to a socket and get back an EWOULDBLOCK
error I have no way of knowing, other than polling, when the socket again
becomes writable. I had hoped that when the state of the socket changed from
blocked to unblocked that a SIGIO would be generated but from my experiments
this appears not to be the case.

The documentation provided by Sun is quite sketchy on this matter but I had
hoped that the behaviour of SUNOS would be similar to 4.3BSD. According to
my BSD documentation when the ASYNC flag is set the kernel watches for a
change in the status of the socket and arranges to send a SIGIO when a
read or write becomes possible.

Does anyone out there know if what I'm trying to do is possible under SUNOS
and if so what I'm doing wrong? Alternatively is there an easier way of
going about solving this sort of problem?

PS. The sockets are stream sockets in the internet domain using tcp protocol.
    The work is being done on a Sun 3/50.

-----------------------------------------------------------------------------
                             Sean Holdsworth.
   EDS Group,   Room 407 IT Building,   Department of Computer Science,
   University of Manchester,   Oxford Road,  Manchester,   M13 9PL,  UK.

   UUCP:  ...!uunet!mcsun!ukc!man.cs!HoldswoS       Fax: +44-61-275-6280

-----------------------------------------------------------------------------

 
 
 

Sockets and interrupt driven I/O

Post by Chris Tor » Wed, 07 Mar 1990 12:31:31



writes:

Quote:>... if I write to a socket and get back an EWOULDBLOCK error I have no
>way of knowing, other than polling, when the socket again becomes writable.
>I had hoped that when the state of the socket changed from blocked to
>unblocked that a SIGIO would be generated but from my experiments this
>appears not to be the case.

If you examine the file netinet/tcp_input.c, you will find code of the
form:

        if (act > so->so_snd.sb_cc) {
                tp->snd_wnd -= so->so_snd.sb_cc;
                sbdrop(&so->so_snd, (int)so->so_snd.sb_cc);
                ourfinisacked = 1;
        } else {
                sbdrop(&so->so_snd, acked);
                tp->snd_wnd -= acked;
                ourfinisacked = 0;
        }
-->  if ((so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel)
                sowwakeup(so);
        tp->snd_una = ti->ti_ack;

The line marked `-->' above is the cuprit:  For the sake of efficiency,
the TCP code calls sowwakeup(so) (a macro for sowakeup(so, &so->so_snd))
only if a process is waiting for data to go out, or is selecting, or was
selecting not long ago.  When a process uses asynchronous I/O, however,
neither SB_WAIT nor sb_sel are set.

There are a number of ways around the problem.  One of them involves no
kernel changes: simply arrange for some process to select on that socket.
Any process will do, including your own.  Thus:

        omask = sigblock(sigmask(SIGIO));
        if ((n = write(socket_fd, buf, count)) < 0 && errno == EWOULDBLOCK) {
                fd_set out;
                struct timeval tv;
                FD_ZERO(&out);
                FD_SET(socket_fd, &out);
                tv.tv_sec = 0;
                tv.tv_usec = 0;
                n = select(socket_fd + 1, (fd_set *)0, &out, (fd_set *)0, &tv);
                if (n > 0) {
                        /* can write now, try again: must have unblocked
                           while we were fiddling with select() */
                        n = write(socket_fd, buf, count);
                        if (n < 0 && errno == EWOULDBLOCK)
                                ... now what? ...
                }
                /* cannot write, but made so->so_snd.sb_sel non nil so that
                   the tcp code will call sowakeup() later */
                n = 0;  /* clobber the error */
        }
        if (n < 0)
                ... handle output error ...
        (void) sigsetmask(omask);

Simpler fixes, if you have kernel source, are to remove the test from
tcp_input.c or to assert SB_WAIT in sosend() when returning EWOULDBLOCK.
(The latter would preserve efficiency, and protect any other code that
has the same bug as tcp_input.c, such as the XNS code [spp_usrreq.c].)
The bug has been fixed in 4.4BSD by removing the test from both
netinet/tcp_input.c and netns/spp_usrreq.c.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)


 
 
 

1. Interrupt driven socket I/O in SUN/Solaris2.5 ?

Hi,

I try to set up a interrupt driven socket routine that would react
on any incoming data (connection demand and normal data). I work
with AF_INET SOCK_STREAM sockets.

I cannot use fork to handle separate connections: I want to handle
them in the same program. So I have one "connection listening" socket
that accept connections and creates normal sockets. I want my interrupt
routine to test for an accept, then to read any incoming data on
the already existing sockets...

It seems that fcntl( sock, F_SETL, FASYNC ) nor fcntl( sock, F_SETOWN...)
works under solaris.

I almost succeed, but it seems that secondary sockets does not inherit
the non-blocking/interrupt-generation properties of the primary socket.

Reply by email please.

David.
+------------------------------------------+

| CEA/Cadarache, DER/SSAE/LSMI, bat 205    |
| 13108 St-Paul-Lez-Durance, FRANCE        |
| tel: (+33) 42254292  fax: (+33) 42252780 |
| http://rhum.cad.cea.fr/                  |
+------------------------------------------+

2. toshiba tecra -> X freeze

3. Interrupt driven socket I/O

4. Network with Windows ME computer?

5. interrupt driven socket handler.

6. Win95 FAT32

7. Interrupt driven socket I/O

8. PCI Profiling/Statistics Tools?

9. Matrox Mystique ands X.

10. Interrupted system call and sockets --> Help

11. Best way to interrupt socket send()?

12. Sockets & interrupts

13. interrupting socket read/write calls