[comp.unix.wizards] Help with select

doug@ws5.cis.temple.edu (Doug Bagley) (03/15/88)

I am trying to learn how to use sockets in Ultrix 2.0 at a site with no
sources.  My problem is with the select function.  When I provide the
readfds and writefds parameters to the select function, only the writefds
parameter gets changed whether or not the process on the other end of the
socket is doing a read or a write.  Strangely enough, if I make the
writefds NULL or 0, and if the remote process is only writing to this
one, everything works fine -- the remote process' writes show up in the
readfds (telling the selecting process that it can read).

Could someone help me out by: correcting any misinterpretation on my
part, or by referring me to a good reference on BSD IPC in the Internet
domain, or perhaps sending me a sample of code that uses select to
multiplex reads and writes at the same time?

I have included a stripped down version of the offending program below.

Thanks in advance,
Doug Bagley
(CSNET: bagley@temple.edu)

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <errno.h>

main(argc, argv)
int	argc;
char	*argv[];
{
    struct	sockaddr_in	sin, from;
    int	i, s, s2, smax, smin, fromlen, mask, writefds[1], readfds[1], nfound;

    /* get the port number from command line arg */
    if (argc != 2) exit(1);
    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s == -1) exit(1);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(argv[1]));
    if (bind(s, (caddr_t)&sin, sizeof(sin)) < 0) exit(1);
    /* listen on specified port */
    listen(s, 5);
    smax = s+1; smin = smax;
    /* mask contains all currently known socket descriptors */
    mask = (1<<s);

    for (;;) {
	readfds[0] = mask;
	writefds[0] = mask;
	/* we currently block forever on select */
	nfound = select(smax, readfds, writefds, 0, 0);
	if (nfound  < 0)
	    perror("select");

	/* test s for new socket connection requests */
	if (readfds[0] & (1<<s)) {
	    s2 = accept(s, &from, &fromlen);
	    if (s2 < 0) {
		if (errno != EINTR)
		  perror("accept");
	    }
	    /* add new socket to mask */
	    mask = mask | (1<<s2);
	    if (s2+1 > smax)  smax = s2+1;
	}

	if (readfds[0] != (1<<s))
	  /* check each known socket to see if it wants to write to us. */
	  for (i=smin; i<=smax; i++)
	    if (readfds[0] & (1 << i) )
	      /* read from the socket and queue message */
	      if (enqueue_msg(i) == -1) {
		  /* peer has closed socket, so close our end of socket */
		  close(i);
		  /* and remove socket from mask */
		  mask = mask & ~(1<<i);
		  /* decrease smax if necessary */
		  if (i+1 == smax) smax--;
	      }

	if (writefds[0] != (1<<s))
	  /* check each known socket to see if it wants to read from us. */
	  for (i=smin; i<=smax; i++)
	    if (writefds[0] & (1 << i))
	      /* remove a message from queue and write it to socket */
	      dequeue_msg(i);

    }
}

sarima@gryphon.CTS.COM (Stan Friesen) (03/21/88)

In article <12404@brl-adm.ARPA> doug@ws5.cis.temple.edu (Doug Bagley) writes:
>I am trying to learn how to use sockets in Ultrix 2.0 at a site with no
>sources.  My problem is with the select function.  When I provide the
>readfds and writefds parameters to the select function, only the writefds
>parameter gets changed whether or not the process on the other end of the
>socket is doing a read or a write.  Strangely enough, if I make the
>writefds NULL or 0, and if the remote process is only writing to this
>one, everything works fine -- the remote process' writes show up in the
>readfds (telling the selecting process that it can read).

	I think you may have a sligght misunderstanding of what a select()
on a write fd means. It means block until there is enough system buffer
space to successfully complete a write on the fd. Since it is almost always
true that there is sufficient buffer space for a write to succeed a select()
on a writefds will almost always return immediately with the writefds altered.
I suspect what you want is to wait until the consumer has read what you last
wrote. This is rather difficult to do, and I will not go into it here.


	SIGH, select() may well be the BSD feature that I miss the most
on System V UNIX. Does Sys 5 release 3 have it or its equivalent?

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/21/88)

In article <2958@gryphon.CTS.COM> sarima@gryphon.CTS.COM (Stan Friesen) writes:
>SIGH, select() may well be the BSD feature that I miss the most
>on System V UNIX. Does Sys 5 release 3 have it or its equivalent?

Yes, it's called poll() and it only works on STREAMS.  AT&T is however
converting the whole character I/O system over to STREAMS and may have
already done so by now.

There is also a SIGPOLL signal available.

sarima@gryphon.CTS.COM (Stan Friesen) (03/28/88)

In article <7513@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>
>Yes, it's called poll() and it only works on STREAMS.  AT&T is however
>converting the whole character I/O system over to STREAMS and may have
>already done so by now.
>
>There is also a SIGPOLL signal available.

	Good, its about time. But... are PIPEs being converted to STREAMS?
If not, then poll() is not fully equivalent to select().

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/28/88)

In article <3025@gryphon.CTS.COM> sarima@gryphon.CTS.COM (Stan Friesen) writes:
>... are PIPEs being converted to STREAMS?

As of Release 3.0, ordinary pipes were still ripped-off block-I/O inodes.
Hidden away somewhere were "stream pipes", but you had to make a special
effort to get them.  I'm pretty sure that a forthcoming release will have
the whole character I/O subsystem converted to STREAMS, but I don't know
if AT&T plans to convert to (full-duplex) stream pipes.  They certainly
ought to; that is one of the most effective tools for user-mode juggling
of streams.