[net.unix-wizards] Can't seem to generate SIGIO. What's the trick?

libes@nbs-amrf.UUCP (Don Libes) (12/06/85)

Ok, I give up.  What's the trick to getting a SIGIO signal?
I wrote a trivial program to do the following:
	signal(SIGIO,sigio_handler);
	open("/dev/ttya",O_RDWR|O_NDELAY);
	fcntl(fd,F_SETFL,FASYNC|FNDELAY);
and then sleep waiting for a SIGIO, but I never get one.

I know I've got data on the port since both select() and ioctl(FIONREAD)
give me the right responses.  Its almost as if FASYNC/SIGIO is not
implemented (on a Sun running 2.0).  Is this the case?

Here's the whole trivial program (which includes tests to confirm all the
system calls return correctly), if my problem is still not obvious.  Please
mail all responses to me.  Thanks VERY MUCH.  

Don Libes        {seismo,umcp-cs}!nbs-amrf!libes

/* simple test of Sun asynchronous I/O */

#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sgtty.h>

static int fd = 0;
int fdwidth;
int readfds, writefds;
char buffer[1024];
int rc;
struct timeval poll;

sigio_handler()
{
	printf("sigio_handler() called\n");
	check_fds();
}

main()
{
	struct sgttyb arg;
	int (*sigrc)();

	/* select() options */
	timerclear(&poll);
	fdwidth = getdtablesize();

	if (BADSIG == signal(SIGIO,sigio_handler)) {
		perror("signal");
		return(-1);
	}

	if (-1 == (fd = open("/dev/ttya",O_RDWR|O_NDELAY))) {
		perror("open(/dev/ttya,O_RDWR|O_NDELAY)");
		return(-1);
	}

	if (-1 == fcntl(fd,F_SETFL,FASYNC|FNDELAY)) {
		perror("fcntl");
		return(-1);
	}

	if (-1 == ioctl(fd,TIOCGETP,&arg)) {
		perror("ioctl(TIOCGETP)");
		return(-1);
	}
	arg.sg_flags |= RAW;
	arg.sg_flags &= ~ECHO;
	arg.sg_ispeed = B9600;
	arg.sg_ospeed = B9600;
	if (-1 == ioctl(fd,TIOCSETP,&arg)) {
		perror("ioctl(TIOCSETP)");
		return(-1);
	}

	check_fds();

	printf("sleeping\n");
	for (;;) {
		printf("available = %d\n",available(fd));
	}
}

/* returns number of chars available for reading on this fd */
int
available(fd)
{
	long count;

	ioctl(fd,FIONREAD,&count);
	return((int)count);
}

check_fds()
{
	int i;

	readfds = 1<<fd;
	writefds = 1<<fd;

	if (-1 == select(fdwidth,&readfds,&writefds,0,&poll)) {
		perror("select");
		return(-1);
	}

	printf("readfds = %x\n",readfds);
	printf("writefds = %x\n",writefds);
	if ((fd > 0) && readfds) {
		int size;

		size = available(fd);
		printf("%d chars ready on input\n",size);
		rc = read(fd,buffer,size);
		if (rc != size) {
			printf("chars read (%d) != chars available (%d)\n",
				rc,size);
		}
		if (rc != -1) {
			buffer[rc] = '\0';
			printf("buffer = %s\n",buffer);
		} else perror("read in check_fds");
	} else {
		printf("no input ready\n");
		rc = read(fd,buffer,1);
		if (rc == -1) perror("read(,,1)");
		else printf("rc = %d   char = %c\n",rc,*buffer);
	}
}

libes@nbs-amrf.UUCP (Don Libes) (12/10/85)

> Ok, I give up.  What's the trick to getting a SIGIO signal?

Thanks very much to Bill Shannon (sun!shannon) for giving me the missing
piece.  His reply was:

	You need to do

		fcntl(fd, F_SETOWN, getpid());

	to set the owner of the fd to you so you'll be the one to get
	the SIGIO.

I refuse to admit how much time I spent reading and rereading the manual
looking for the solution.  I think I'll mark the spot in my manual where
this is so clearly documented with a large ax.

Don Libes       {seismo,umcp-cs}!nbs-amrf!libes