[comp.unix.programmer] Using Nonblocking I/O and LWP

bergquis@nms.gdc.portal.com (Brett Bergquist) (06/24/91)

Has anyone been successful using Sun's non-blocking I/O library and the
Light Weight Process library together?

I have created an application in which I have a set of file
descriptors that I will receive (udp) messages on.  The main task sets
up a select(2) using the file descriptors that I will receive messages
on.  Each time a message arrives on a file descriptor, a task is created
to handle the message.

My problem is that even though I do not include "stdin" in the set of file
descriptors that select(2) should monitor, whenever there is input on
"stdin", select(2) returns indicating that input is available on the other
descriptors, even when it is not.  Below is example code from the Sun
Programmer's Overview that I have added a select(2) call in.  When I run
this application in a shelltool and hit return, select(2) returns as
described above.

This only happens the first task has been created.

This gets me into a case where I attempt to process input that will
never appear.

Any ideas on what to do?

--------------------------- server.c ------------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <lwp/lwp.h>
#include <lwp/stackdep.h>
#include <lwp/lwperror.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>

#define MYPORT 8889
#define MAXPRIO 10
#define BUFSIZE 10

struct message
{
    int timeout;
    int msgsize;
    char buf[BUFSIZE];
} message;
extern int errno;

main()
{
    int s;
    struct sockaddr_in addr;
    int len = sizeof(struct sockaddr_in);
    int fromlen;
    int rlen;
    void compute();
    stkalign_t* sp;
    caddr_t loc;
    close(0);

    if (pod_setmaxpri(MAXPRIO) < 0)
    {
	lwp_perror("pod_setmaxpri");
	_exit(1);
    }
    if (lwp_setstkcache(5000, 5) < 0)
    {
	lwp_perror("lwp_setstkcache");
	_exit(1);
    }
    if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
	perror("can't get socket");
	_exit(1);
    }
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_family = AF_INET;
    addr.sin_port = MYPORT;
    if (bind(s, (struct sockaddr*) &addr, len) < 0)
    {
	perror("bind");
	close(s);
	_exit(1);
    }
    if (getsockname(s, (caddr_t)&addr, &len) != 0)
    {
	perror("can't get name");
	close(s);
	_exit(1);
    }
    for (;;)
    {
	do
	{
	    fd_set readfds;
	    
	    fromlen = len;
	    FD_ZERO(&readfds);
	    FD_SET(s, &readfds);
	    switch (select(64, &readfds, NULL, NULL, NULL))
	    {
	      case -1:
		perror("select");
		break;
	      case 0:
		printf("select returned 0\n");
		continue;
		break;
	      default:
		printf("select return\n");
		if (FD_ISSET(s, &readfds))
		{
		    printf("waiting for a message\n");
		    rlen = recvfrom(s, (caddr_t)&message,
				    sizeof(struct message), 0, &addr,
				    &fromlen);
		}
		break;
	    }
	} while ((rlen == -1) && (errno == EINTR));
	if (rlen == -1)
	{
	    perror("recvfrom");
	    close(s);
	    _exit(1);
	}
	sp = lwp_datastk(message.buf, message.msgsize, &loc);

	lwp_create((thread_t*) 0, compute, MINPRIO, 0, sp, 2,
		   message.timeout, loc);
    }
    exit(0);
}

void compute(timeout, msg)
    int timeout;
    char* msg;
{
    struct timeval time;
    time.tv_sec = timeout;
    time.tv_usec = 0;

    printf("%s\n", msg);
    lwp_sleep(&time);
    printf("%s slept %d secs\n", msg, timeout);
}

------------------------------- slp.c ---------------------------------------
;
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>

#define MYPORT 8889
#define BUFSIZE 10

struct message
{
    int timeout;
    int msgsize;
    char buf[BUFSIZE];
} message;

extern int errno;

main(argc, argv)
    int argc;
    char** argv;
{
    int s;
    struct sockaddr_in addr;
    int len = sizeof(struct sockaddr_in);
    int err;
    struct hostent *hp;
    char* server;

    if (argc != 4)
    {
	printf("usage: %s server seconds message\n", argv[0]);
	exit(2);
    }
    server = argv[1];
    message.timeout = atoi(argv[2]);
    message.msgsize = strlen(argv[3]) + 1;
    bcopy(argv[3], message.buf, message.msgsize);
    if ((hp = gethostbyname(server)) == 0)
    {
	printf("can't get host name\n");
	exit(1);
    }
    bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
    addr.sin_family = AF_INET;
    addr.sin_port = MYPORT;

    if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
	perror("can't get socket");
	exit(1);
    }
    do
    {
	err = sendto(s, (caddr_t)&message, sizeof(message), 0, &addr, len);
    } while ((err == -1) && (errno = EINTR));
    if (err == -1)
    {
	perror("sendto");
	exit(1);
    }
    exit(0);
}

-- 
Brett M. Bergquist, Principal Engineer | "Remind me" ... "to write an
General DataComm, Inc.,                | "article on the compulsive reading
Middlebury, CT 06762                   | of news." - Stranger in a Strange Land
Email: bergquis@nms.gdc.portal.com  or ...!portal!gdc!nms!bergquis